Cgridview Ajax Question

I’ve been searching around, and I can’t find any posts or examples where my particular scenario applies. Maybe that’s because what I’m trying to do is inefficient, or there’s a better way to do it. I’ve tried a few different solutions, and nothing is getting me where I need to be. Here’s the goal:

Some of my columns in the cgridview are drop downs/text boxes. When these change, I need an ajax function to fire and add a class to the appropriate box or drop-down. This is all working. The problem is, I’d like to reload the cgridview (or even better, just the row,) before adding the classes, because one of the columns contains another, concatenated with a string. You can see I commented out the yiiGridView.update line, because both the addClass and the update were firing at the same time, causing the class to be added for a split second, and the grid to be updated.

Is there any way to do this with cgridview’s built-in ajax functions, or is there a simpler way to achieve this?

Here’s my current view:





<?php 

Yii::app()->getClientScript()->registerCssFile(Yii::app()->baseUrl .'/css/my_admin.css');


Yii::app()->clientScript->registerScriptFile(Yii::app()->baseUrl.'/js/jeditable/jquery.jeditable.mini.js', CClientScript::POS_HEAD); 


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

    $('[class^=editable]').live('change', function () {

    	var userID = $(this).parent().parent().attr('data-user_id');

    	var attribute = $(this).attr('name');

    	$.ajax({

    		url: '".$this->createUrl('user/ajaxUpdate&attribute=')."'+attribute,

    		type: 'POST',

    		cache: false,

    		data: {'User[id]':userID, 'User[attribute]': $(this).val()},

    		dataType: 'json',

    		success: function(data)

    		{

    		 //\$.fn.yiiGridView.update('user-grid');

    		\$('tr[data-user_id='+data.id+']').children('td').children('input[name='+data.attribute+']').addClass('success');


    		},

    		});

    })",CClientScript::POS_READY);

?>




<?php

/* @var $this UserController */

/* @var $model User */


$this->breadcrumbs=array(

	'Users'=>array('index'),

	'Manage',

);


$this->menu=array(

	array('label'=>'List User', 'url'=>array('index')),

	array('label'=>'Create User', 'url'=>array('create')),

);

?>


<h1>Manage Users</h1>


<p>

You may optionally enter a comparison operator (<b>&lt;</b>, <b>&lt;=</b>, <b>&gt;</b>, <b>&gt;=</b>, <b>&lt;&gt;</b>

or <b>=</b>) at the beginning of each of your search values to specify how the comparison should be done.

</p>


<?php $form=$this->beginWidget('CActiveForm', array(

    'enableAjaxValidation'=>true,

)); ?>

 


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

	'id'=>'user-grid',

	'dataProvider'=>$model->search(),

	'filter'=>$model,

	'rowHtmlOptionsExpression'=> 'array("data-user_id"=>$data->id)',

	'columns'=>array(

        array(

        'id'=>'autoId',

        'class'=>'CCheckBoxColumn',

        'selectableRows' => '50',   

        ),

		array(

		'type'=>'raw',

		'name'=>'firstName',

		'value'=>'CHtml::textField("firstName",$data->firstName, array("size"=>10, "class"=>"editable", "data-attribute"=>"firstName"));'

		),

		array(

		'type'=>'raw',

		'name'=>'lastName',

		'value'=>'CHtml::textField("lastName",$data->lastName, array("size"=>10, "class"=>"editable"));'

		),

		array(

		'type'=>'raw',

		'name'=>'extension',

		'value'=>'CHtml::textField("extension",$data->extension, array("size"=>10, "class"=>"editable"));'

		),

		'lineport',

		array(

		'name'=>'company_name',

		'value'=>'$data->customer->company_name',

		),

       'site' => array(

                'type'=>'raw',

                'value' => 'CHtml::dropDownList(\'site_id\', $data->site_id, 

                			$data->customer->getSiteOptions(),

                			array(\'class\'=>\'editable-site_id\')

                			)',

                'name' => 'site'

        ), 

		array(

		'name'=>'endpoint',

		'value'=>'$data->endpoint[\'mac_address\']',

		),

		array(

			'class'=>'CButtonColumn',

		),

	),

)); ?>







<?php echo CHtml::ajaxSubmitButton('#',array('#'), array(),array("style"=>"display:none;")); ?>

<?php echo CHtml::ajaxSubmitButton('Delete Selected',array('gridUpdate','action'=>'delete'), array('success'=>'$.fn.yiiGridView.update(\'user-grid\')')); ?>

<?php $this->endWidget(); ?>






use the afterAjaxUpdate callback that yii provides add this In your gridview and write the callback function


<script>

function name_of_the_callback() {

   // update the class

   // other stuff

}

</script>


your CGridView stuff

...

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

        'id'=>'user-grid',

        'dataProvider'=>$model->search(),

        'filter'=>$model,

        'rowHtmlOptionsExpression'=> 'array("data-user_id"=>$data->id)',


        'afterAjaxUpdate'=>'js:name_of_the_callback',  // it will only fire the callback once the grid is updated

        

         ... your other stuff


)); ?>




.....

I tried that, but it seems that afterAjaxUpdate runs during the initial page load, and that my function doesn’t register as an Ajax update. I also tried using a callback function in the function used to reload the grid (on the road right now, not sure exactly what the syntax was,) but it seems like it doesn’t wait until the Ajax request is done, and the page has finished whatever it’s doing. The class shows for a split second, then disappears

I don’t understand why it does that I have used it like bazillion time you probably have something that is causing that effect to take place do pastie of your whole view

Here’s an example I just tested: When you load the page, the callback function is run.




<script>

function setClass(myvariable)

{

alert(myvariable);

}


</script>





<?php 

Yii::app()->getClientScript()->registerCssFile(Yii::app()->baseUrl .'/css/my_admin.css');


#Yii::app()->clientScript->registerScriptFile(Yii::app()->baseUrl.'/js/jeditable/jquery.jeditable.mini.js', CClientScript::POS_HEAD); 


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

    $('[class^=editable]').live('change', function () {

    	var userID = $(this).parent().parent().attr('data-user_id');

    	var attribute = $(this).attr('name');

    	$.ajax({

    		url: '".$this->createUrl('user/ajaxUpdate&attribute=')."'+attribute,

    		context: this,

    		type: 'POST',

    		async: false,

    		cache: false,

    		data: {'User[id]':userID, 'User[attribute]': $(this).val()},

    		dataType: 'json',

    		success: function(data)

    		{

       		\$.fn.yiiGridView.update('user-grid', 

       		{

       		context: this,

       		complete: function(data){

       		\$(this).addClass('error');

       		}

       		

       		}  );

    		//\$('tr[data-user_id='+data.id+']').children('td').children('input[name='+data.attribute+']').addClass('success');

    		},

    		complete: function(data)

    		{

    		\$(this).addClass('error');

			\$(this).addClass('error');

    		},

    		});

    })",CClientScript::POS_READY);

?>




<?php

/* @var $this UserController */

/* @var $model User */


$this->breadcrumbs=array(

	'Users'=>array('index'),

	'Manage',

);


$this->menu=array(

	array('label'=>'List User', 'url'=>array('index')),

	array('label'=>'Create User', 'url'=>array('create')),

);

?>


<h1>Manage Users</h1>


<p>

You may optionally enter a comparison operator (<b>&lt;</b>, <b>&lt;=</b>, <b>&gt;</b>, <b>&gt;=</b>, <b>&lt;&gt;</b>

or <b>=</b>) at the beginning of each of your search values to specify how the comparison should be done.

</p>


<?php $form=$this->beginWidget('CActiveForm', array(

    'enableAjaxValidation'=>true,

)); ?>

 


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

	'id'=>'user-grid',

	'dataProvider'=>$model->search(),

	'afterAjaxUpdate'=>'js:setClass(\'test\')',

	'filter'=>$model,

	'rowHtmlOptionsExpression'=> 'array("data-user_id"=>$data->id)',

	'columns'=>array(

        array(

        'id'=>'autoId',

        'class'=>'CCheckBoxColumn',

        'selectableRows' => '50',   

        ),

		array(

		'type'=>'raw',

		'name'=>'firstName',

		'value'=>'CHtml::textField("firstName",$data->firstName, array("size"=>10, "class"=>"editable", "data-attribute"=>"firstName"));'

		),

		array(

		'type'=>'raw',

		'name'=>'lastName',

		'value'=>'CHtml::textField("lastName",$data->lastName, array("size"=>10, "class"=>"editable"));'

		),

		array(

		'type'=>'raw',

		'name'=>'extension',

		'value'=>'CHtml::textField("extension",$data->extension, array("size"=>10, "class"=>"editable"));'

		),

		'lineport',

		array(

		'name'=>'company_name',

		'value'=>'$data->customer->company_name',

		),

       'site' => array(

                'type'=>'raw',

                'value' => 'CHtml::dropDownList(\'site_id\', $data->site_id, 

                			$data->customer->getSiteOptions(),

                			array(\'class\'=>\'editable-site_id\')

                			)',

                'name' => 'site'

        ), 

		array(

		'name'=>'endpoint',

		'value'=>'$data->endpoint[\'mac_address\']',

		),

		array(

			'class'=>'CButtonColumn',

		),

	),

)); ?>







<?php #echo CHtml::ajaxSubmitButton('#',array('#'), array(),array("style"=>"display:none;")); ?>

<?php #echo CHtml::ajaxSubmitButton('Delete Selected',array('gridUpdate','action'=>'delete'), array('success'=>'$.fn.yiiGridView.update(\'user-grid\')')); ?>

<?php $this->endWidget(); ?>



Ok, I changed the callback to


setClass(id, data){alert(id);} 

Now the function loads only when the ajax function is completed. I’m just too much of a newb to understand why at the moment. Now I just need to figure out how to get $(this) (the input field that triggered the original ajax call, into the ‘afterAjaxUpdate’ callback. At first glance, it doesn’t look like a good fit for my purposes, as it appears to only give you access to ‘id’ and ‘data’, but I need to add a class to the single row and column that kicked of the original ajax call.