YII not generating Javascript code

Hi, guys. First post. Very newbie and non native english speaker, please be patient.

I’m trying to implement the classical dependable dropdown solution from [url="http://www.yiiframework.com

/wiki/24/"]http://www.yiiframework.com/wiki/24/[/url] but the ajax request is not being triggered.

In summary, I want a dropdown populated with categories and when a category is selected the products dropdown is populated with the corresponding products via ajax.

Here is the code:




<?php

//table Product: columns id,categoryId,description

//table ProductCategory: columns id,description


$product=new Product();

$productCategory=new Productcategory();


$form=$this->beginWidget('CActiveForm');

echo $form->dropDownList($productCategory,'id',

                        CHtml::listData($productCategory::model()->findAll(),'id','description'),

                        array('ajax'=>array(

                            'url'=>CController::createUrl('market/dynamicProducts'),

                            'update'=>'#'.CHtml::activeId($product,'id')

                            )

                        )

);    

echo $form->dropDownList($product,'id',array());

$this->endWidget();

?>



Checking Firebug, no request is generated. The rendered page HTML is as follows:




<form id="yw0" action="/mm/index.php/market/product" method="post">

   <select name="Productcategory[id]" id="Productcategory_id">

      <option value="1">Steel products</option>

      <option value="2">Wood products</option>

      <option value="3">Fasteners</option>

      <option value="4">Bearings</option>

      <option value="10">Furniture</option>

      <option value="11">Bedding</option>

   </select>

   <select name="Product[id]" id="Product_id">

   </select>

</form>



Yii didn’t generate any Javascript code to handle the ajax request. I’ve tried to force the script generation adding the following code:




<?php

Yii::app()->clientScript->registerScript('dropdown',

        "$(".CHtml::activeId($productCategory,'id').").change(function(){"

        . "jQuery.ajax({'url':'".CController::createUrl('market/dynamicProducts')."',"

        . "'cache':false,"

        . "'success':function(html){"

            . "jQuery(".CHtml::activeId($product,'id').").html(html);}"

        ."});"

        ."return false;"

        ."});"

);

?>



Again, no Javascript generated and the HTML output is identical to the previous attempt.

The only solution I found was to add the <script> tag manually:




<script src="/mm/assets/2d1fd728/jquery.js" type="text/javascript"></script>


<script>

    $(Productcategory_id).change(function(){

        jQuery.ajax({'url':'/mm/index.php/market/dynamicProducts',

            'data':jQuery(this).serialize(),

            'cache':false,

            'type':'POST',

            'success':function(html){

                jQuery(Product_id).html(html);

            }

        }

        );

        return false;

    }

    );

</script>



It is strange that 2 different methods failed to generate the Javascript code. Even more strange is that when I use CHtml::ajaxLink the Javascript code is generated.

Is there any Yii setting or server configuration that may be blocking Javascript generation?

Hi mogul, welcome to the forum.

Sorry if you have already checked this, but did you check the entire html output? I mean, not just a small part around the dropdowns. Yii usually renders the registered javascripts just before the ending </body> tag.

My bad for not posting the entire html output. It is really empty outside the form:




<html>

    <head>

    </head>

    <body>

        <form id="yw0" action="/mm/index.php/market/product" method="post">

            <select name="Productcategory[id]" id="Productcategory_id">

                <option value="1">Steel products</option>

                <option value="2">Wood products</option>

                <option value="3">Fasteners</option>

                <option value="4">Bearings</option>

                <option value="10">Furniture</option>

                <option value="11">Bedding</option>

            </select>

            <select name="Product[id]" id="Product_id">

            </select>

        </form>

    </body>

</html>



I am accessing the action directly from the browser with localhost/mm/index.php/market/product and using renderPartial to avoid any “contamination” from the layout code (it also doesn’t work when I render my main page and navigate to the product page, but my main page is full of Javascript generated by ajaxLink from my navbar).

Here is product action code:




//MarketController

public function actionProduct()

	{

		$this->renderPartial('product');

	}



That’s it.

Please look up the API for renderPartial() and processOutput()

http://www.yiiframework.com/doc/api/1.1/CController#renderPartial-detail

In general, it’s a good idea to use the renderPartial for the response of an ajax call. And the processOutput parameter for the method should be usually left untouched. By using the default value of ‘false’, you can exclude js code in the ajax response which tends to make things complicated in the event handling.

In other words, it’s better to send all the necessary js code at the time of initial page loading and use only plain html (or json data) for the subsequent ajax loading.

Try ‘render’ in your ‘actionProduct’ and ‘renderPartial’ in ‘actionDynamicProducts’.

[EDIT]

In addition, you have to use the following syntax in attaching an event handler to an element which will be dynamically updated by ajax:


jQuery('static-container-selector').on('change', 'dynamic-input-selector', function(){});



rather than


jQuery('dynamic-input-selector').on('change', function(){});

or

jQuery('dynamic-input-selector').change(function(){});



When you use the latter syntax, you will lose the attached event handler when the dynamic input is updated by an ajax call.

It worked!

I knew it was a newbie question… It seems that I was not very good studing Yii rendering process. Back to the book. And back to JQuery too, thanks for the extra tip. I told you I’m VERY newbie.

Thank you very much for your help! Faith in Yii restored!

You’re welcome.

But they are not that newbie issues, IMO. There seems to be many people who don’t know the tips.

(The first part may be a bit controversial. I believe that there could be a situation in which you have to include javascript code in the ajax response. In fact, that’s what the processOutput parameter is for.)

BTW, I don’t believe you are a sheer newbie. <_<

I know that you read and write very good both in English and PHP/javascript.

Thanks for the kind words. It is just my google / ctrl-c / ctrl-v technique. You will notice that the code skeleton is available all over the web.

Regarding the JQuery stuff, Yii generated the following code:




jQuery('body').on('change','#Productcategory_id',function(){...});



Which is according to your recommended syntax:




jQuery('static-container-selector').on('change', 'dynamic-input-selector', function(){});



It seems that ‘body’ is not a good ‘static-container-selector’. Maybe JQuery(’#yw0’) which is the form id would be better. Anyway, it works.

I managed to google the issue and found http://stackoverflow.com/questions/15090942/jquery-event-handler-not-working-on-dynamic-content which leads to http://api.jquery.com/on/#direct-and-delegated-events. It seems to be a good starting point to study the issue.