How to unbind CGridView 'selectionChanged' event to prevent duplicating on ajax

Hi All,

I have some issues with events duplicating.

I have 1 CGridView on page, and then I click on row it will raises ‘selectionChanged’ event of CGridView which loads thru renderPartial another one CGridView and pastes it after the first one. In the second CGridView I have another ‘selectionChanged’ event (for example, it shows alert).

The problem is when I clicking row in the first table multiple times (to see different data samples) and then clicking row in the second table it raises event multiple times.

So, for example, if I selected 5 times rows in the first table and then select any row in the second table, the ‘alert’ event raises 4-5 times one after other.

Here is my controller:


	public function actionIndex()

	{

		/*Yii::app()->clientScript->registerScriptFile(

		    Yii::app()->assetManager->publish(Yii::getPathOfAlias('webroot').'/js/calls.js'),

		    CClientScript::POS_HEAD

		);*/

		$model = new User;


		if(isset($_REQUEST['uid'])){

			$user_id = (int)$_REQUEST['uid'];

			$campaign_ids = Company::model()->searchCampaignsByUserId($user_id);

			Yii::app()->clientscript->scriptMap['jquery.js'] = false;

			Yii::app()->clientscript->scriptMap['jquery.yiigridview.js'] = false;

			Yii::app()->clientscript->scriptMap['calls.js'] = false;

			Yii::app()->clientscript->scriptMap['jquery.ba-bbq.js'] = false;

			$this->renderPartial('_campaigns', array('campaign_ids'=>$campaign_ids, 'user_id'=>$user_id), false, true);

			Yii::app()->end();

		}

		$this->render('index', array('model'=>$model));

	}

View index.php


<h1><center>Calls</center></h1>

<div id="call-agents-table">

<?php echo $this->renderPartial('_callagents', array('model'=>$model)); ?>

</div><!-- call-agents-table -->

<div id="call-agent-campaigns" style="display:none"></div><!-- call-agent-campaigns -->

View _callagents (first grid)


<?php 

Yii::app()->clientScript->registerScript('get_user_info', "

var getUserInfo = function(id){

	user_id = parseInt($.fn.yiiGridView.getSelection(id));

	if(isNaN(user_id))

		return;

	data = {

		uid: user_id

	}

	$.ajax({

		data: data,

		cache: false,

		success: function(html){

			$('#call-agent-campaigns').html(html).slideDown();

		}

	});

};

",CClientScript::POS_END);


$this->widget('zii.widgets.grid.CGridView', array(

	'id'=>'callagents-grid',

	'dataProvider'=>$model->searchUsersByRole('callagent'),

	'columns'=>array(

		'firstname',

		'lastname',

		'email',

	),

	'selectionChanged'=>"js:getUserInfo",

)); ?>

View campaigns (second grid which is loaded thru ajax and renderPartial)


<?php 

Yii::app()->clientScript->registerScript('get_user_campaign_info', "

var alertFromCallsJS = function(id){

	campaign_id = parseInt($.fn.yiiGridView.getSelection(id));

	if(isNaN(campaign_id))

		return;

	alert('alert from another function');

}

",CClientScript::POS_END);


$switch_caching = YII_DEBUG?'false':'true'; //enable cahching on production

$this->widget('zii.widgets.grid.CGridView', array(

	'id'=>'callagent-campaigns-grid',

	'dataProvider'=>Campaign::model()->getCampaignsByIds($campaign_ids),

	'filter'=>Campaign::model(),

	'selectionChanged'=>"js:function(id){

		

		alert('this message will popup several times after clicking the first table');

	}",

	'columns'=>array(

		'campaign_name',

		array(

			'header'=>'Division',

			'value'=>'$data->division',

			),

		'starting_date',

	),

)); 

?>

Playing with unbinds and others (undelegate, die, off) didn’t produce any results. I think there is solution with unbind’s but I don’t know where to apply it.

As temporary (not good) solution I have assigned to every grid unique id.

Hi. Have similar bug in my application. I tried several solutions but invain. Then looked at jquery.yiigridview.js and found that it binds the click event on "document".

I tried a small patch at jquery.yiigridview.js code (around line 95):




				if (settings.selectableRows > 0) {

					selectCheckedRows(this.id);

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



change to




				if (settings.selectableRows > 0) {

					selectCheckedRows(this.id);

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




So the click is bound to the grid and not to the whole document: however, this solution will break the click after ajax update :S

FYI: For a simple test i changed the code in the jquery.yiigridview.js that the framework copies into the asset folder.

I’m investigating further for other solutions

In your case, having different ids is the best solution. I used to have grid in different CJuiDialogs. In my case i found that the best solution is to unbind events related to the grid wherever the dialog is closed with:




$(document).off('click', '#my_grid_id .items > tbody > tr')



This solution works perfectly! Thank you so much!