Need help creating a dependant dropdown

Hi all,

I’m working under Yii 1.1.5. I’ve been given an existing project and asked to make one dropdown dependent on another’s selected value. I’ve read (and been trying for 2 days) the wiki page Creating a dependent dropdown as well as the forum post [Solved] How to create dependent DropDown Lists but still I cannot make my second dropdown to show some values.

I can say I’m a n00b (doing my internship) and I really need help, so thanks in advance to anyone who could help me.

Here is the original code :

  • Controller : TicketsController.php

class TicketsController extends CRootController {


    public function actionCreate() {


            Yii::app()->clientScript->registerScriptFile( Yii::app()->baseUrl .'/javascript/ui.datepicker-fr.js', CClientScript::POS_END);


        $priorities = Yii::app()->db->createCommand("SELECT priority_id, label FROM tickets_priorities ORDER BY sorting")->queryAll();

        $types = Yii::app()->db->createCommand("SELECT type_id, label FROM tickets_types ORDER BY sorting ASC, label ASC")->queryAll();

        $projects = Yii::app()->db->createCommand("SELECT p.project_id, CONCAT_WS(' ', p.site, '(',p.version,')') as site FROM projects p JOIN projects_users pu ON pu.project_id=p.project_id WHERE p.est_valide='1' AND pu.user_id='". Yii::app()->user->id ."' ORDER BY site")->queryAll();


        if( Yii::app()->request->isPostRequest ) {


            mb_ereg("([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})", $_POST['Ticket']['deadline'], $regs );

            $deadline = $regs[3] .'-'. $regs[2] .'-'. $regs[1];


            $query = "INSERT INTO tickets (project_id, status_id, user_id, assignUser_id, priority_id, type_id, title, description, deadline,date_creation, date_modified)

                      VALUES (:project_id, '1','". Yii::app()->user->id ."', :assignUser_id, :priority_id, :type_id, :title, :description, :deadline, NOW(), NOW() )";

            $command = Yii::app()->db->createCommand( $query );

            $command->bindParam(':project_id' , $_POST['Ticket']['project_id'], PDO::PARAM_INT );

            $command->bindParam(':assignUser_id' , $_POST['Ticket']['assignUser_id'], PDO::PARAM_INT );

            $command->bindParam(':priority_id' , $_POST['Ticket']['priority_id'], PDO::PARAM_INT );

            $command->bindParam(':type_id'     , $_POST['Ticket']['type_id'], PDO::PARAM_INT );

            $command->bindParam(':title'       , $_POST['Ticket']['title'], PDO::PARAM_STR );

            $command->bindParam(':description' , $_POST['Ticket']['description'], PDO::PARAM_STR );

            $command->bindParam(':deadline' , $deadline, PDO::PARAM_STR );


            $command->execute();


            $id = Yii::app()->db->lastInsertID;


        //

        // AssignUsers

        //

        $query = "SELECT u.user_id, CONCAT(u.lastname, ' ', SUBSTR(u.name, 1, 1), '.') AS user

            FROM users u

            JOIN AuthAssignment aa ON aa.userid=u.user_id

            WHERE (aa.itemname='developpeur'

            OR aa.itemname='admin'

            OR aa.itemname='rapporteur')

            AND u.est_valide=1

            ORDER BY user";

            //$assignUsers[0] = '';

            $assignUsers = Yii::app()->db->CreateCommand( $query )->queryAll();


        $this->render('form', array('priorities' => $priorities,

                                    'types' => $types,

                                    'projects' => $projects,

                                    'assignUsers' => $assignUsers ) );

    }

  • View : form.php

<div id="submenu">

    <?php echo CHtml::link('Liste des tickets', array('tickets/index') ); ?>

    |

    <strong>Créer un ticket</strong>

</div>


<?php echo CHtml::form('', 'post', array('enctype' => 'multipart/form-data', 'class'=>'formulaire') ); ?>

<div class="tickets-grid-header">

    <?php echo CHtml::submitButton('Enregistrer'); ?>&nbsp;&nbsp;&nbsp;

</div>




    <fieldset>

        <p>

            <label>Site</label>

            <?php echo CHtml::dropDownList('Ticket[project_id]', '', CHtml::listData( $projects, 'project_id', 'site' ) ); ?>

        </p>

        <p>

            <label>Titre</label>

            <input type="text" name="Ticket[title]" value="<?php echo $Ticket['title']; ?>" />

        </p>

        <p>

            <label>Priorité</label>

            <?php echo CHtml::dropDownList('Ticket[priority_id]', '', CHtml::listData( $priorities, 'priority_id', 'label' ) ); ?>

        </p>

        <p>

            <label>Nature</label>

            <?php echo CHtml::dropDownList('Ticket[type_id]', '', CHtml::listData( $types, 'type_id', 'label' ) ); ?>

        </p>

        <p>

            <label>Asssigné à</label>

            <?php echo CHtml::dropDownList('Ticket[assignUser_id]', $ticket['assignUser_id'], CHtml::listData( $assignUsers, 'user_id', 'user' ) ); ?>

        </p>

        <p>

            <label>Deadline</label>

            <input type="text" name="Ticket[deadline]" id="ticket_deadline" />

        </p>

        <p>

            <label>Description</label>

            <textarea name="Ticket[description]" style="width:66%;max-height:300px" class="elastic"><?php echo $Ticket['description']; ?></textarea>

        </p>

        <p>

            <label>Ajouter des pièces jointes</label>

            <?php $this->widget('CMultiFileUpload', array('name' => 'TicketAttachments',

                                                          'accept' => 'doc|docx|xls|xlsx|jpg|gif|png|psd|zip|rar|html|swf|pdf') );

            ?>

        </p>

    </fieldset>

</form>

<div class="tickets-grid-footer">

</div>


<?php Yii::app()->clientScript->registerScriptFile( Yii::app()->theme->baseUrl .'/js/jquery.elastic.js', CClientScript::POS_END ); ?>

<script type="text/javascript">

$( function() {

    $('#ticket_deadline').datepicker({ minDate: new Date() });

    $('.elastic').elastic();

});

</script>

And here is the code as I modified it :

  • Controller : TicketsController.php

class TicketsController extends CRootController {


	//Fonction utilisée pour remplir la dropDownList "Assigné à" en fonction des valeurs de la dropDownList "Site"

	public function actionDynamicassignusers()

	{

		$query = "SELECT u.user_id, CONCAT(u.lastname, ' ', SUBSTR(u.name, 1, 1), '.') AS user 

			FROM users u 

			JOIN projects_users pu ON u.user_id = pu.user_id 

			WHERE project_id = :project_id";

		

		$command = Yii::app()->db->createCommand($query);

		$command->bindValue(':project_id', $_POST['Tickets']['project_id'], PDO::PARAM_INT );

		$data = $command->queryAll();

		

		$data=CHtml::listData($data,'user_id','user');

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

		{

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

		}

	}




	// Création d'un nouveau ticket

    public function actionCreate() {


		//Script pour affichage datepicker dans le champ "Deadline"

        Yii::app()->clientScript->registerScriptFile( Yii::app()->baseUrl .'/javascript/ui.datepicker-fr.js', CClientScript::POS_END);

		

		//alimentation des dropdownlists

		$projects = Yii::app()->db->createCommand("SELECT p.project_id, CONCAT_WS(' ', p.site, '(',p.version,')') as site FROM projects p JOIN projects_users pu ON pu.project_id=p.project_id WHERE p.est_valide='1' AND pu.user_id='". Yii::app()->user->id ."' ORDER BY site")->queryAll();

        $priorities = Yii::app()->db->createCommand("SELECT priority_id, label FROM tickets_priorities ORDER BY sorting")->queryAll();

        $types = Yii::app()->db->createCommand("SELECT type_id, label FROM tickets_types ORDER BY sorting ASC, label ASC")->queryAll();

        

		//insertion en BDD des données postées par l'utilisateur

        if( Yii::app()->request->isPostRequest ) {


            mb_ereg("([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})", $_POST['Ticket']['deadline'], $regs );

            $deadline = $regs[3] .'-'. $regs[2] .'-'. $regs[1];


            $query = "INSERT INTO tickets (project_id, status_id, user_id, assignUser_id, priority_id, type_id, title, description, deadline,date_creation, date_modified)

                      VALUES (:project_id, '1','". Yii::app()->user->id ."', :assignUser_id, :priority_id, :type_id, :title, :description, :deadline, NOW(), NOW() )";

            $command = Yii::app()->db->createCommand( $query );

            $command->bindParam(':project_id' , $_POST['Ticket']['project_id'], PDO::PARAM_INT );

            $command->bindParam(':assignUser_id' , $_POST['Ticket']['assignUser_id'], PDO::PARAM_INT );

            $command->bindParam(':priority_id' , $_POST['Ticket']['priority_id'], PDO::PARAM_INT );

            $command->bindParam(':type_id'     , $_POST['Ticket']['type_id'], PDO::PARAM_INT );

            $command->bindParam(':title'       , $_POST['Ticket']['title'], PDO::PARAM_STR );

            $command->bindParam(':description' , $_POST['Ticket']['description'], PDO::PARAM_STR );

            $command->bindParam(':deadline' , $deadline, PDO::PARAM_STR );


            $command->execute();


            $id = Yii::app()->db->lastInsertID;


        //

        // AssignUsers

        //

        /*$query = "SELECT u.user_id, CONCAT(u.lastname, ' ', SUBSTR(u.name, 1, 1), '.') AS user

            FROM users u

            JOIN authassignment aa ON aa.userid=u.user_id

            WHERE (aa.itemname='developpeur'

            OR aa.itemname='admin'

            OR aa.itemname='client')

            AND u.est_valide=1

            ORDER BY user";

            //$assignUsers[0] = '';

            $assignUsers = Yii::app()->db->CreateCommand( $query )->queryAll();*/

			

			

        $this->render('form', array('projects' => $projects,

				    'priorities' => $priorities,

                                    'types' => $types,                                    

                                    //'assignUsers' => $assignUsers 

		                 	) );

    }

  • View : form.php

<div id="submenu">

    <?php echo CHtml::link('Liste des tickets', array('tickets/index') ); ?>

    |

    <strong>Créer un ticket</strong>

</div>


<?php echo CHtml::form('', 'post', array('enctype' => 'multipart/form-data', 'class'=>'formulaire') ); ?>

<div class="tickets-grid-header">

    <?php echo CHtml::submitButton('Enregistrer'); ?>&nbsp;&nbsp;&nbsp;

</div>




    <fieldset>

        <p>

            <label>Site</label>

            <?php echo CHtml::dropDownList('Ticket[project_id]', '', CHtml::listData( $projects, 'project_id', 'site' ),

			array(

			'ajax' => array(

			'type'=>'POST',

			'url'=>CController::createUrl('tickets/dynamicassignusers'),

			'update'=>'#TicketAssignUser_id',

			//'data'=>array('Ticket[project_id]'=>'js:this.value'),

			))); ?>

        </p>

        <p>

            <label>Titre</label>

            <input type="text" name="Ticket[title]" />

        </p>

        <p>

            <label>Priorité</label>

            <?php echo CHtml::dropDownList('Ticket[priority_id]', '', CHtml::listData( $priorities, 'priority_id', 'label' ) ); ?>

        </p>

        <p>

            <label>Nature</label>

            <?php echo CHtml::dropDownList('Ticket[type_id]', '', CHtml::listData( $types, 'type_id', 'label' ) ); ?>

        </p>

        <p>

            <label>Assigné à</label>

            <?php echo CHtml::dropDownList('TicketAssignUser_id', '', array()); ?>

        </p>

        <p>

            <label>Deadline</label>

            <input type="text" name="Ticket[deadline]" id="ticket_deadline" />

        </p>

        <p>

            <label>Description</label>

            <textarea name="Ticket[description]" style="width:66%;max-height:300px" class="elastic"></textarea>

        </p>

        <p>

            <label>Ajouter des pièces jointes</label>

            <?php $this->widget('CMultiFileUpload', array('name' => 'TicketAttachments',

                                                          'accept' => 'doc|docx|xls|xlsx|jpg|gif|png|psd|zip|rar|html|swf|pdf') );

            ?>

        </p>

    </fieldset>

</form>

<div class="tickets-grid-footer">

</div>


<?php Yii::app()->clientScript->registerScriptFile( Yii::app()->theme->baseUrl .'/js/jquery.elastic.js', CClientScript::POS_END ); ?>

<script type="text/javascript">

$( function() {

    $('#ticket_deadline').datepicker({ minDate: new Date() });

    $('.elastic').elastic();

});

</script>

I’d first recommend using the javascript debugger in your browser to determine where the process is going wrong. You should be able to check that the correct event is being fired and that the asynchronous request is being sent, and then check the response from the server. Once you’ve narrowed the problem down and potentially received an error message from the server, it should be easier to figure out the problem.

I tend to use the debugging tools built in to chrome, but other people may be able to recommend better tools.

Ok Thank you Keith for your answer. I don’t know exactly how to use the javascript debugger but I’m gonna try to.

Otherwise, does your answer imply that my code seems to be correct ?

Edit : when I look under the console tab of firebug, I have an error saying :

jQuery("body").delegate is not a function

followed by some code.

Under the console tab of Chrome, I have the following :

[i]Uncaught TypeError: Object #<Object> has no method ‘delegate’ [right]index.php:121[/right]

(anonymous function) [right]index.php:121[/right]

o.extend.ready.o.readyList [right]jquery.min.js:19[/right]

o.extend.each [right]jquery.min.js:12[/right]

o.extend.ready [right]jquery.min.js:19[/right]

o.each.o.fn.(anonymous function) [right]jquery.min.js:19[/right][/i]

Edit bis: according to Qiang, The delegate function requires jquery 1.4.2. whereas in my CRootController.php file I can see Yii::app()->clientScript->registerScriptFile(‘htétépé://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js’ ,CClientScript::POS_HEAD);

Should I replace the 1.3.2 with the 1.4.2 (without risking some features not working anymore) or should I add the 1.4.2 next to the 1.3.2 ?

Well I have replaced 1.3.2 with 1.4.2 in the CRootController.php file :


//

        // Script map

        //

        Yii::app()->clientScript->scriptMap = array(

            'jquery.js' => 'htétépé://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js',

            'jquery-ui.js' => 'htétépé://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js',

        );


        //

        // Script jquery

        //

        Yii::app()->clientScript->registerScriptFile('htétépé://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js' ,CClientScript::POS_HEAD);

        Yii::app()->clientScript->registerScriptFile('htétépé://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js', CClientScript::POS_END);

The debugger doesn’t show any error message anymore, but my second dropdownlist still doesn’t show any values…

any suggestions ? Pleeaase !! :)

Have you made sure that the asynchronous request is being fired?

In Chrome Developer Tools, go to the Network tab before refreshing your page. You should see the timeline of all of your page resources loading. When you change the value in the first drop down box, an entry should be added to the bottom of the network page. You’ll be able to click the entry to see the request and response, which should give you some idea of the problem.

I haven’t looked to determine if your code is correct yet, it’ll be easier if you can determine whether the issue lies in the javascript involved in sending the request, in the PHP code on the server, or in the javascript that handles the returning data.

Thanks again Keith for answering…

Actually it works all fine since I replaced 1.3.2 with 1.4.2 in the CRootController.php file.

I hadn’t seen it at once because I had to change the selected value in the first dropdown so that the corresponding values showed in the second dropdown. The second dropdown wasn’t fed directly when the page loaded.

I wanted to edit my post yesterday but I couldn’t since I’m a “newbie” on this forum…

So your first answer really helped me and I’m grateful to you !

I think this post can be marked as "solved".

Thanks again !

Yiaan

No probs, glad I could help.