Dependat DropDown not working

Hi guys,

It is regarding the dependent dropdown functionality I am looking to achieve in my web application. I have spent so many hours trying different things but not able to solve the problem. I would appreciate your help in this regard.

MYSQL Tables (under discussion): MainProfileTable, Cities

MainProfileTable Model Name: MainProfileTable.php

MainProfileTable controller Name: MainProfileTableController.php

Cities Model Name: Cities.php

Following is the code in MainProfileTableController.php




public function actionCities()

  {

  

      $cities = Cities::model()->findAll('country_name=:c_name',array(':c_name'=>$_POST['Country']));

        

      $data = CHtml::listData( $cities, 'country_name', 'city_name' );


      foreach ( $data as $value => $name )

      {

         echo CHtml::tag( 'option', array( 'value' => $value ), CHtml::encode( $name ), true );

      }


  }



Following is the code in _form.php file of the MainProfileTable views:




////////////////// this code is at the begining of the file ////////////////////

<div class="form">


<?php $form=$this->beginWidget('CActiveForm', array(

	'id'=>'main-profile-table-form',

	'enableAjaxValidation'=>false,

)); ?>

/////////////////////////////////////////////////////////////////////////////////


//then this is the code under discussion:


<div class="row">

		<?php echo $form->labelEx($model,'Country'); ?>

		<?php echo $form->dropDownList($model,'Country',MainProfileTable::getCountriesDBOptions(),array('style'=>'width:300px'),array('ajax'=>array('type'=>'GET',

                                 'url'=>CController::createUrl('mainProfileTable/cities'), 

                                 'update'=>'#City'))); ?>

		<?php echo $form->error($model,'Country'); ?>

	</div>


  <div class="row">

		<?php echo $form->labelEx($model,'City'); ?>

		<?php echo $form->dropDownList($model,'City',array(),array('style'=>'width:300px')); ?>

		<?php echo $form->error($model,'City'); ?>

	</div>



Following is the access control in controller file:




	public function accessRules()

	{

		return array(

			array('allow',  // allow all users to perform 'index' and 'view' actions

				'actions'=>array('index','view','cities'),

				'users'=>array('*'),

			),

			array('allow', // allow authenticated user to perform 'create' and 'update' actions

				'actions'=>array('create','update','cities'),

				'users'=>array('@'),

			),

			array('allow', // allow admin user to perform 'admin' and 'delete' actions

				'actions'=>array('admin','delete'),

				'users'=>array('admin'),

			),

			array('deny',  // deny all users

				'users'=>array('*'),

			),

		);

	}



That is all I have been working on. Please figure out where the problem lies. It does not give any error as such but do not display any values.

I also tried populating data in actionCities() function manually/static. Even then it loads nothing.

Awaiting quick response.

Regards

There are already many "dependand dropdowns" threads on this forum… try to search a bit for them…

In your case… you use


'update'=>'#City'

but if you check the HTML source u will see that you don’t have that ID anywhere.

hi mdomba,

thank you for reply. i have gone through almost all of these threads including the cookbook/yii provided article on these but unable to get it sorted.

would really need attention. i replaced #City with #MainProfileTable_City after viewing code but that even did not work. it seems like ccontroller::createURL is doing nothing as i tried putting test manual data too.

For the ID is better to use activeID() - http://www.yiiframework.com/doc/api/1.1/CHtml#activeId-detail

Next you need to debug a bit… check with firebug to see if the ajax call is made… what data is sent and what is returned…

It looks like as AJAX request is not working at all. If I try to access Cities controller directly from the address bar and pass Country parameter with a value as UK, then it shows the values through GET. Another problem is identified as it shows only one record and that is the last row of the that particular country.

Also do we have to do something here:


<?php $form=$this->beginWidget('CActiveForm', array(

        'id'=>'main-profile-table-form',

        'enableAjaxValidation'=>false,

)); ?>



I mean do we have to set enableAjaxValidation to true, or it can stay same as above.

Firebug displaying following in POST request:

http://www.test.com/HGsSee/index.php/mainProfileTable/cities 200 OK 400ms

Response is BLANK.

What could be the cause?

Well… you first need to make the actionCities work as intended so that is dispaly all the data you need…

AjaxValidation is not needed for this… as you see the ajax call is made… you just need to find out why there is no response… check what parameters are sent with the call…

edit: and check what is the variable name for the parameter sent so that you can use it in the action with $_POST

Thanks mdomba,

Managed to fix the AJAX POST issue. Now it is returning data at least. But the problem is that it now only one record from the Cities table against the country selected. Whereas there are more than one Cities in the database table.

I tried it two different ways:

No 1:


  public function actionCities()

  {   $criteria = new CDbCriteria;

$criteria->select = 'country_name,city_name';

$criteria->condition = 'country_name=$_POST['MainProfileTable']['Country']';

$criteria->order = 'city_name ASC';

$cities = Cities::model()->findAll($criteria);


       

      $data = CHtml::listData( $cities, 'country_name', 'city_name' );


      foreach ( $data as $value => $name )

      {

         echo CHtml::tag( 'option', array( 'value' => $value ), CHtml::encode( $name ), true );

      }


  }

No: 2


  public function actionCities()

  {   $cities = Cities::model()->findAll('country_name=:c_name',array(':c_name'=>$_POST['MainProfileTable']['Country']));

        

      $data = CHtml::listData( $cities, 'country_name', 'city_name' );


      foreach ( $data as $value => $name )

      {

         echo CHtml::tag( 'option', array( 'value' => $value ), CHtml::encode( $name ), true );

      }


  }

Both shows one record from the table and that is last record

why you use listdata?

How do I fix it then. I don not know the purpose of this. I just took code from the forum and pasted in my code.

Please guide the best way to do. Thanks

The listData is not so important here… you can use it or not…

you need to check the result of findAll… you have there country_name is that the name or the ID… the parameter you are sending is the name or ID?

I really appreciate for helping me out. You are making my life easier.

Also Thank you for letting me know the no need of listData. I did it this way.




      foreach ( $cities as $value )

      {

         echo CHtml::tag( 'option', array( 'value' => $value->city_name ), CHtml::encode( $value->city_name ), true );

      }



Now it populates all. I added record in database and it worked fine. Another problem now:

When I come back to update the same record, the City field comes blank and do not fill with existing data and I can understand the reason as well but do not know how to fix it.




  <div class="row">

		<?php echo $form->labelEx($model,'Country'); ?>

		<?php echo $form->dropDownList($model,'Country',MainProfileTable::getCountriesDBOptions(),array('ajax'=>array('type'=>'POST',

                                 'url'=>CController::createUrl('cities'), 

                                 'update'=>'#MainProfileTable_City'))); ?>

		<?php echo $form->error($model,'Country'); ?>

	</div>


  <div class="row">

		<?php echo $form->labelEx($model,'City'); ?>

		<?php echo $form->dropDownList($model,'City',array(),array('style'=>'width:300px')); ?>

		<?php echo $form->error($model,'City'); ?>

	</div>



As you can see the City as blank array due to the onchange function applied above which fills it through AJAX. But now when we want to update it how to deal with this problem.

like you wrote… the cities dropdown is populated on change event… but when you render the view on update… the change event is not fired… so you need to "manually" give it the inital values depending on the current value of the first dropdown

Briliant.

Sorted that out.

Many many thanks mdomba for your help in all the matters.

Finally fixed it after continous effort of 7 hours.

Regards

YL

Great!

Would be nice if you would post your working code… This way somebody in the future can get great help from this thread…

helo i am new to yii. i have one question. how can a fill a dropdown box with some value based on the onchange event of another drop down box.

Hello Noufal. Welcome to Yii and the forum. Have you read this very topic from the beginning? I believe it’s very clear. What don’t you understand in it?