CGridView loaded by AJAX. multiple events problem / events not attached

Hi all.

Problem:

  • CGridView doesn’t have events attached (sort, filter, pagination doesnt work)

  • or CGridView table loaded by ajax request has multiple events attached to filters, paginators, sort elements.

There’s a page where I have to select a 2 users from a 2 different huge list os users. To display these users I’m using CGridView table displayed in popups. I’m loading each CGridView table dynamically via ajax request. The action responsible for rendering page works in 2 ways.




// JQuery is already loaded by parent page so disable loading them here

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

    'jquery.js'     => false,

    'jquery.min.js' => false,

);


if (isset($_POST['register_script'])) {

    // FIRST REQUEST

    $content = $this->renderPartial('popupSelect', array(

        'key_holder'      => $key_holder,

        'register_script' => isset($_POST['register_script']) ? $_POST['register_script'] : 0,

        'uniqid'          => $_GET['uniqid'],

        ), true, $_POST['register_script']); // second false - dont load jscripts and styles

    echo json_encode(array('content' => $content,));

} else {

    // SORT, SEARCH, PAGINATION REQUESTS

    $content = $this->renderPartial('popupSelect', array(

        'key_holder'      => $key_holder,

        'register_script' => isset($_POST['register_script']) ? $_POST['register_script'] : 0,

        'uniqid'          => $_GET['uniqid'],

        ), true, true);

    echo $content;

}



  • For the very first request I’m setting $_POST[‘register_script’] = 1 and it will generate a page encoded as json and I’m displaying it in popup. FIRST REQUEST is parsed

  • For the second and other requests variable $_POST[‘register_script’] is set to = 0 so scripts are not loaded anymore (as 4th parameter is 0). FIRST REQUEST is parsed as well.

  • For every ajax call caused by filter, sort or pagination request SORT, SEARCH, PAGINATION REQUESTS is parsed so Yii can "work" with it in its own way.

AND IT WORKS PERFECTLY FINE.

Problem starts when I’m trying to select second user from different popup which contains different CGridView table with different data. CGridView loads but sort, pagination or filter functions doesn’t work and simple redirects me to the page displaying only the CGridView table. I guess table is not “initialized” and events are not attached to the table elements. (I don’t know how to do it manually and if I will know the other problems are irrelevant.)

To solve that I set register_script to 1 for every attempt of opening popup where CGridView table is included. Script which loads second CGridView is almost the same. Different models are used only. (Instead of key_holder there’s engineer) and it works perfectly.

So every attempt of loading content into popup loads all scripts (4th parameter is set to true).

This works perfectly fine as well to this point.

If I will try to open popup with previous CGridView table again then events are attached again to the new CGridView table again so every sort, filter or pagination request is generated twice. Every attempt of opening other popups adds another events. It works but this is wrong. How to prevent register these events again ?

Any help appreciated.

Regards

Mario

I wonder if I am talking to myself …

[list=1][]I use NLSClientScript (which serves to include javascripts from ajax);[]I applied changes to Yii (not considered as a bug)[/list][size="2"]


CButtonColumn:


To remove the 'on' event on a grid before setting it.


if(true) {

				$class=preg_replace('/\s+/','.',$button['options']['class']);

                $js[]="if(typeof(_gridf)==='undefined'){_gridf={};}"

                ."if(typeof(_gridf['on-{$this->grid->id}-{$class}'])!=='undefined') {jQuery(document).off('click','#{$this->grid->id} a.{$class}',_gridf['on-{$this->grid->id}-{$class}']);}"

                ."_gridf['on-{$this->grid->id}-{$class}']=$function;"

                ."jQuery(document).on('click','#{$this->grid->id} a.{$class}',_gridf['on-{$this->grid->id}-{$class}']);";

} else {

				$class=preg_replace('/\s+/','.',$button['options']['class']);

				$js[]="jQuery('#{$this->grid->id} a.{$class}').live('click',$function);";

}




jquery.yiigridview.js:


Add lines to switch off event listeners before defining them.

added:			$(document).off('click.yiiGridView', '#' + id + ' .' + settings.tableClass + ' > tbody > tr');

original:		$(document).on('click.yiiGridView', '#' + id + ' .' + settings.tableClass + ' > tbody > tr', function (e) {


added:			$(document).off('click.yiiGridView', '#' + id + ' .select-on-check-all');

original:		$(document).on('click.yiiGridView', '#' + id + ' .select-on-check-all', function () {


				$(document).off('change.yiiGridView keydown.yiiGridView', settings.filterSelector);

				$(document).on('change.yiiGridView keydown.yiiGridView', settings.filterSelector, function (event) {


-> There is a potential issue that there are other listeners using the same selector that might be deleted.

-> However, the risk is low because the selector is specific and likely to be used by the yiiGridView only.



[/size]