[solved] AJAX update in CGridView

I would like to have a CGridView column which will toggle a boolean value when clicked upon.

e.g. I have a field called ‘enabled’ in my database table, but instead of the user having to go in to each record to update the value to yes/no it would be a lot easier if they could do this on the grid.

How can I implement this functionality?

Just for the record, I created this example which does exactly what you want to do, based on a CButtonColumn (a button labeled Publish/Unpublish in this case).

My guess is that you probably can accomplish this with less effort, using a CCheckBoxColumn.

Edit:

Or perhaps add checkbox conrols to a CDataColumn (I can’t remember the exact reason why I, some time ago, considered that solution).

/Tommy

Hi tri,

Actually it just needs to be a hyperlink (not a button/checkbox). Clicking on the link will toggle between yes and no.

I had a look at your example but I’m not sure how to adapt it for a hyperlink…

It will be rendered as an ajaxLink so I think that will fit your need. What makes it a bit complicated is the two different ways to set the label (initially vs feedback from controller action). And as mentioned, I should have chose a different name than ‘ajax’ for the array key I added.

/Tommy

OK I’ve done it like this:




array(

        'name'=>'enabled',

	'type'=>'raw',

        'value'=>'CHtml::ajaxLink("$data->IsEnabled", "index.php?r=admin/town/ajaxupdate", array(

             "data"=>array(

                   "id"=>$data->id,

             ),

             "update"=>"#town-grid",

        ));',

),






public function actionAjaxUpdate()

{

	if(isset($_GET['id']))

	{

		$model=$this->loadModel();

		$model->enabled = ($model->enabled == 1 ? 0 : 1);

		$model->update();

	}

}



The link is rendered and works fine, only problem is it’s not a “proper” ajax call, i.e. the URL is reloaded and the grid disappears after the link is clicked. The field is however been updated in the database. What have I missed out?

I think I’ve figured out what is causing the grid to disappear: The ‘update’ parameter that is being passed into ajaxLink:

What I obviously need it to do is update the text that is displayed in the hyperlink from ‘Yes’ to ‘No’ (or vice versa)

Try ‘success’ instead of ‘update’, something like




'success'=>'js:'

  .'function(id){'

    .'$.fn.yiiGridView.update("'.$target_container.'", {url:""});'

  .'}',



note 1: the quoting can be simplified

note 2: $target_container should be replaced by town-grid

note 3: I don’t remember why I added the empty url attribute

/Tommy

Cheers mate, I’m just giving that a go now…

What is “$.fn.” ? I’m getting an error on that…

Normally same as "jQuery.fn".

BTW, I just return an record id from the controller in my example. Not used for updating the grid (I think it makes it’s own ajax call, have to check the framework scripts to recall).

/Tommy

I think the quoting is messing it up for me, I keep getting these Parse errors.

Simplified




'success'=>'js:function(id){$.fn.yiiGridView.update("town-grid", {url:""});}',



(not tested)

/Tommy

OK finally got that to parse properly - again the database is updated but the link text does not update.

Had a look in Firebug console and there is nothing in the "Response" tab - do I need to return a JSON with the value "Yes" or "No" ? Surely that could be simplified somehow, i.e. if the link gets clicked then it just needs to toggle the values (providing the update was successful).

I’m out of suggestions on this (obviously you use a CDataColumn). BTW, I forgot to mention CLinkColumn but I don’t know if it’s usable (so far I haven’t tried it). Perhaps you should have another look at my CButtonColumn example (at least the label change will work). You can define a second button column if you want some separation from the default buttons.

/Tommy

So anyone have any suggestions?

BUMP

Here is the solution:

JQuery Function:


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

$('#supplier-grid a.ajaxupdate').live('click', function() {

	$.fn.yiiGridView.update('supplier-grid', {

		type: 'POST',

		url: $(this).attr('href'),

		success: function() {

			$.fn.yiiGridView.update('supplier-grid');

		}

	});

	return false;

});

");

CGridView column:


array(

	'name'=>'enabled',

	'type'=>'raw',

	'value'=>'CHtml::link($data->IsEnabled, array("ajaxupdate", "id"=>$data->id), array("class"=>"ajaxupdate"));',

),

Controller:


public function actionAjaxUpdate()

{

	$model=$this->loadModel();

	$model->enabled = ($model->enabled == 1 ? 0 : 1);

	$model->update();

}

Simply you can use like this


public function actionAjaxUpdate()

{

	$model=$this->loadModel();

	$model->enabled = 1-$model->enabled; //UPDATED LINE

	$model->update();

}

Let’s play safe and avoid malfunction in case of other representations of true




  $model->enabled = $model->enabled ? 0 : 1;



PHP reference

/Tommy

Great example, thank you :)

Although I needed to modify the controller slightly for it to work by adding the ID, I also changed formula to .not.




	public function actionAjaxUpdate($id)

	{

			$model=$this->loadModel($id);

			$model->enabled = (!$model->enabled);

			$model->update();

	}



hi friends

i am using this code and find an error "403 you are not authorised to perform this action "

can anyone tell how to fix it …