DDD: 2 Models on a 3rd Models form

Ok first things first. I was very hesitant to create another thread on the topic of Dependent Dropdowns but I have been through the wiki and a multitude of threads on creating a dependent dropdown.

In my current scenario I am working with a form and trying to use a dependent dropdown that grabs the values from two other different models.

I am to the point where I am not getting anymore problems displaying in Firebug so hopefully someone can put me on the right track because things are not working.

With the code below both of the dropdowns are properly "displaying" but there is no functionality (i.e. when I select a Category, nothing happens with the SubCategory)

db structure:


OrgCatChosen.(OrgCatChosenId, SubCategoryId, OrganizationId)

Category.(CategoryId, Name)

SubCategory.(SubCategoryId, CategoryId, Name)

Current code:

OrgCatChosenController:


public function actionDynamicSubCategories()

  {	

    $data=Category::model()->findAll('CategoryId=:CategoryId', 

		array(':CategoryId'=>(int) $_POST['OrgCatChosen']['CategoryId']));

		

    public function actionDynamicSubCategories()

	{

		$data=Category::model()->findAll('CategoryId=:CategoryId', 

					  array(':CategoryId'=>(int) $_POST['OrgCatChosen']['CategoryId']));

	    

		$data=CHtml::listData($data,'CategoryId','Name');

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

			{

				echo CHtml::tag('option',

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

			}

	

	}

  }




public function accessRules() {

  return array(

    ...

    array('allow', 

      'actions'=>array('minicreate', 'create', 'update', 'admin', 'delete', 'DynamicSubCategories'),

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

    ),



OrgCatChosen/_form:


<div class="row"> 

<label>Category</label>

<?php

  echo GxHtml::dropDownList('CategoryId','', GxHtml::listDataEx(Category::model()->findAll(),'CategoryId', 'Name'),

    array(

      'ajax' => array(

      'type'=>'POST', 

      'url'=>CController::createUrl('OrgCatChosen/DynamicSubCategories'),

      'update'=>'#'.CHtml::activeId($Subcategory,'SubcategoryId')

    )

  )); 

 ?>

</div><!-- row -->


<div class="row"> 

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

  <?php echo GxHtml::dropDownList('subCategory','',  

            GxHtml::listData(SubCategory::model()->findAll(),'SubCategoryId','Name'));

  ?>

</div><!-- row -->



Anybody have an idea here? Been fighting with it for a couple of days.

Your actionDynamicSubCategories() does not output anything !

Anyway… If you want to learn how to do the dropdowns… I would suggest you not to only read the wiki article… but to make an example that works… only this way you will understand how all components works together…

mdomba, I don’t come here to ask a question until I have exhausted my skills and I am truly stuck. I am not asking for someone to write all my code that is why I have presented what I have (I updated my controller code btw as I pasted the wrong section).

I have seen you post in many threads about dependent dropdown for people to just complete the wiki exercise. Trust me if I was able to understand things there I wouldn’t be asking this question now. I am not the only one in this boat. I appreciate all the input that everyone provides on this forum, in the wiki’s, on irc, and the entire community on and off this website… but I have seen it written many times over that people just do not understand that article. Sure there are many that do and obviously have a skill set far greater than myself or others having problems. I don’t try to fool anyone and say that I am a star coder, I am on the learning path and work at it daily.

If I just opened up a question and said something to the tune of “Can someone write the code for a dependent dropdown that fits my situation” or cut and paste the code from others and wonder why it didn’t work in my situation directly like others have done, I would appreciate your response. In my case I have provided my code that I have, explained that I have spent countless hours on the situation, and been through the array of materials that is available on the subject, and I am still stuck. Judge me as you will once you respect my efforts I have put into it. To top things off I didn’t ask for someone to rewrite my code to a working matter either…from my original post “so hopefully someone can put me on the right track because things are not working.”

Thanks, only long winded so you understand I am not one looking for a handout, just a bit of help.

I think the reason why this question crops up all the time is that people neglect to add to the wiki article in question when they figure it out…

jacmoe, very true. I update at least my forum post with the complete details so there is always that future reference for others.

My intent here is to rewrite that wiki in another form to include the complete details so people can see how it evolves from cradle to grave to help others in my situation. I am sure that will help alleviate all these posts on the subject. To inlclude this one that I was so hesitant to start.

I appriciate your comment… but you have to understand my point of view…

yes you posted your code… but that code was incomplete… and I could not have known that it is incomplete… you put only an assignement to the $data variable… and because of that… you got my response… that IMO was appropriate for the kind of code you posted…

now you updated that same code… .so it does not matter…

but for sake of others that will read that code and that maybe knows even less than you… please edit again your code as you have still some errors there…

the actionDynamicSubCategories() is declared twice…

NOTE: Just a personal opinion… when you get some answers… it’s better to post new information / code as a new post… .than to edit the previous one… as then some posts loose meaning…

As for your problem here… I still think that you need to read the wiki article and check the code there very good… as there the code is right… but you did not make the same…

Explanation:

Check the wiki article and notice the name of the method is


actionDynamiccities()... 

and it’s called as


'url'=>CController::createUrl('currentController/dynamiccities')

Did you see the difference?

Spoiler - big letter "D" in method name but lower "d" in the call to createUrl - and in the rules…

mdomba thanks for coming back and posting. I do know that you are very active and helpful around here, but I wanted to explain that I am putting in the work on my end before I even come here for help. So now I think we both understand where each other is coming from.

You are right I messed up even worse by trying to edit the code in my first post. Going back and comparing what exists in the code here and my code is different.

So here is my current code, updated with the info you provided on naming:

OrgCatChosenController:


public function actionDynamicsubcategories()

  {

    $data=Category::model()->findAll('CategoryId=:CategoryId', 

        array(':CategoryId'=>(int) $_POST['OrgCatChosen']['CategoryId']));

    $data=CHtml::listData($data,'CategoryId','Name');

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

        {

          echo CHtml::tag('option',

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

        }

  }




public function accessRules() {

  return array(

    ...

    array('allow', 

      'actions'=>array('minicreate', 'create', 'update', 'admin', 'delete', 'dynamicsubcategories'),

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

    ),

OrgCatChosen/_form:


<div class="row"> 

<label>Category</label>

<?php

  echo GxHtml::dropDownList('CategoryId','', 

        GxHtml::listDataEx(Category::model()->findAll(),'CategoryId', 'Name'),

    array(

      'ajax' => array(

      'type'=>'POST',

      'url'=>CController::createUrl('OrgCatChosen/dynamicsubcategories'), 

      'update'=>'#'.CHtml::activeId($Subcategory,'SubcategoryId')

      )

  )); 

?>       

</div><!-- row -->

		

<div class="row"> 

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

 <?php 

    echo GxHtml::dropDownList('subCategory','', 

        GxHtml::listData(SubCategory::model()->findAll(),'SubCategoryId','Name'));

?>       

</div><!-- row -->

I have also tried using this is my view.


echo GxHtml::dropDownList('subCategory','', array());

I know in the the wiki it says "//empty since it will be filled by the other dropdown" and others said to populate it. Either way I am not even to that point as I still do not have any of that functionality existing.

Now that I have my current code as it exists in my app can you see where I am going wrong? Or is there some tool that I can use to help me troubleshoot my problem? I am not seeing any errors in Firebug as mentioned but that does not mean I am looking for the right things.

Just to remain complete, I did go back to the wiki and cross reference things and try to see what I am missing, again it is beyond me though.

All these views in a couple of days and still no one can help?

While you are creating the 2nd dropDownList with an ID of “subCategory”, you are referencing it with an ID of something like “Subcategory_SubCategoryID”. This may be the reason why ajax can’t update your 2nd dropDownList.

So, the solution might be …




  echo GxHtml::dropDownList('CategoryId','', 

        GxHtml::listDataEx(Category::model()->findAll(),'CategoryId', 'Name'),

    array(

      'ajax' => array(

      'type'=>'POST',

      'url'=>CController::createUrl('OrgCatChosen/dynamicsubcategories'), 

-     'update'=>'#'.CHtml::activeId($Subcategory,'SubcategoryId')

+     'update'=>'#subCategory')

      )

  )); 



@softark,

I owe you a million thanks. With your input AJAX functionality started working and from there I was able to continue t/s and rewrite my code to come to a working solution.

I intend to do a more complete write up on the subject but in the mean time so everyone can see the solution as it stands.

OrgCatChosenController:


public function actionDynamicsubcategories()

  {

    $data=SubCategory::model()->findAll('CategoryId=:CategoryId', 

        array(':CategoryId'=> $_POST['CategoryId']));


    $data=CHtml::listData($data,'SubCategoryId','Name');

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

        {

          echo CHtml::tag('option',

              array('value'=>$id),CHtml::encode($value),true);

        }

  }




public function accessRules() {

  return array(

         ...

         array('allow', 

	   'actions'=>array('minicreate', 'create', 'update', 'admin', 'delete', 'dynamicsubcategories'),

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

	 ),

OrgCatChosen/_form:


<label>Category</label>

<?php

  echo GxHtml::dropDownList('CategoryId','', 

           GxHtml::listDataEx(Category::model()->findAll(),'CategoryId', 'Name'),

         array(

         'ajax' => array(

              'type'=>'POST', 

              'url'=>CController::createUrl('OrgCatChosen/dynamicsubcategories'), 

              'update'=>'#subCategory'

	       )

  )); 

?>




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

<?php echo GxHtml::dropDownList('subCategory','', array()); ?>

I was on a job trip yesterday so I could not help you…

softark got the point right :D

@enfield… as you can now see… the wiki article is writen very good… and it works if you use it’s code… as there activeId() is not used…

activeId() generates input field ID for a model attribute… so it should be used with CActiveForm::dropDownList() or with CHtml::activeDropDownList() not with CHtml::dropDownList() … you just mixed the code from the wiki and code from some dd threads… :)

Maybe now you will better understand why I non-stop write… read the wiki… .do the example there… and only when you get that example working… and understand how it works… try to make a custom dependand dropdown…

@mdomba, I won’t argue the point that the code in the wiki works it is more or less the trouble of understanding it. That’s all I am asking you to respect. As with anything in this world everyone is on a different level and there are too many of us that have struggled with understanding things simply by doing that wiki. For me I do not learn from someone writing my code or simply cutting and pasting a given example and trying to figure out what the missing blanks are. Maybe as I progress with coding that will change.

I guess I am not out of the water yet on this one though. Although my code is working for the dependent dropdown when I submit my form it throws the error telling me to pick a SubCategory still.

Brain is fried for the night though and need some sleep.

mdomba, taking the info you posted I am trying to switch these dropdown lists to use CActiveForm. With the code below when I select Category the entire list of SubCategories appears in the SubCategory dropdown, not just the associated SubCategories per given Category.

OrgCatChosenController: old code commented out


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

<?php

//echo GxHtml::dropDownList('CategoryId','', GxHtml::listDataEx(Category::model()->findAll(),'CategoryId', 'Name'),

echo $form->dropDownList($model, 'categoryId', 

          GxHtml::listDataEx(Category::model()->findAll(),'CategoryId', 'Name'),

  array(

    'ajax' => array( 

    'type'=>'POST', 

    'url'=>CController::createUrl('OrgCatChosen/dynamicsubcategories'), 

    //'update'=>'#subCategory', 

    'update'=>'#'.GxHtml::activeId($model,'subCategory'),

  )

)); 

?>




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

<?php //echo GxHtml::dropDownList('subCategory','', array()); ?>

<?php echo $form->dropDownList($model,'subCategory',array()); ?>

added in model/BaseOrgCatChosen to work with the Category dropdown list:


private $_categoryId = null;

public function getCategoryId()

{

  if ($this->_categoryId === null && $this->subCategory !== null && $this->subCategory->category !== null)

  {

    $this->_categoryId = $this->subCategory->category->Name;

  }

  return $this->_categoryId;

}

public function _categoryId($value)

{

  $this->_categoryId = $value;

}

As I mentioned in a previous post when I select a SubCategory and submit it throws the error saying the Sub Category must be provided.

Am I taking the right approach here?

Did you change your OrgCatChosenController::actionDynamicsubcategories() ?

I think there’s no need to change that …

I think it’s a proper and necessary change if your Category model has a property named “subCategory”. But be careful with the name. Is it really “subCategory”?

I don’t understand the intention of the code above. How is it related to the dropDownList?

Besides that, it’s not a good practice to give confusing names to methods and variables: $_categoryId, getCategoryId() and _categoryId() are not for “ID” but “Name” in your implementation.

I believe it’s a very bad sign … Please don’t make it your unconscious habit.

Um, as a whole, I think you should try to change things one by one, step by step, confirming each change you have made is really working. Not just you alone, but all of us should. :)

softark, thanks again for the feedback.

No I left that alone

subCategory comes from this in the model:


public function relations() {

  return array(

   'organization' => array(self::BELONGS_TO, 'Organization', 'OrganizationId'),

   'subCategory' => array(self::BELONGS_TO, 'SubCategory', 'SubCategoryId'),

  );

}

To answer your confusion above…


private $_categoryId = null;

public function getCategoryId()

...

This is to define a relationship to get the Name from Category. Since SubCategory is related to Category with CategoryId I needed something to get to Category.Name. You are right with the naming on that one and I should change it to something like categoryName.

Regardless these are not the issues that are not allowing the submitting of the form. From the wiki others have created widgets to allow the selected values to be submitted in a form. The widget only encloses the CHTML. This seems like overkill to me since I believe CActiveForm is just a wrapper of CHTML. Since I have CHTML working I just want to change that into CActiveForm so the selected values from the dropdown will be imported into the db through the form.

So, because your property in the model is "SubCategoryId", then the 2nd dropDownList in the form should be:




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

<?php echo $form->dropDownList($model,'SubCategoryId',array()); ?>



softark,

Thanks for sticking with me on this one. With your help it is now working as one would expect!

Hi guys,

I follow the below code and it works. But when i want update the info, i only can see category value and the SubCategoryId is empty value…




public function relations() {

  return array(

   'organization' => array(self::BELONGS_TO, 'Organization', 'OrganizationId'),

   'subCategory' => array(self::BELONGS_TO, 'SubCategory', 'SubCategoryId'),

  );

}




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

<?php

echo $form->dropDownList($model, 'categoryId', $model->getCatgeoryOptions(),

  array(

    'ajax' => array( 

    'type'=>'POST', 

    'url'=>CController::createUrl('default/dynamicsubcategories'), 

    'update' => '#' . CHtml::activeId($model, 'SubCategoryId'),

  )

)); 

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

<?php echo $form->dropDownList($model,'SubCategoryId',array()); ?>