Delete In Cgridview Not Working

I have a view that was created by Gii. As far as I understand, clicking the delete button in the grid should bring up a confirmation dialog and then send a POST request. However when I try it, I don’t get a confirmation and a GET request is sent.

Any ideas on how I can track this down?




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

	'id'=>'user-grid',

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

	'filter'=>$model,

	'columns'=>array(

		'username',

		'email',

		'profile',

		array(

			'class'=>'CButtonColumn',

		),

	),

));



Is your page generating javascript errors at any point?

No, no JS errors at any point.

Usually CGridView will write a javascript function for "delete" button like the following:




$(document).on('click','#your-grid-id a.delete',function() {

	if(!confirm('Are you sure you want to delete this item?')) return false;

	var th=this;

	var afterDelete=function(){};

	$.fn.yiiGridView.update('your-gird-id', {

		type:'POST',

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

		data:{ 'YII_CSRF_TOKEN':'99e5ffb865cbe9186e92e0f65340c05078e25471' },

		success:function(data) {

			$.fn.yiiGridView.update('your-grid-id');

			afterDelete(th,true,data);

		},

		error:function(XHR) {

			return afterDelete(th,false,XHR);

		}

	});

	return false;

});



Do you have something like this in your HTML output?

If yes, then by using the developer’s tool of your browser, you can set a break point in the first line of this function, and examine what’s happening.

I guess the chances are, as Keith suggests, there’s a javascript error in your code somewhere else other than this function.

Just a thought… do you have javascript enabled at all ?

Thanks for your replies, guys.

@softark: Yes, I have that piece of code in the page. Considerably less nicely formatted though:




<script type="text/javascript">

/*<![CDATA[*/

jQuery(function($) {

jQuery('a[rel="tooltip"]').tooltip();

jQuery('a[rel="popover"]').popover();

$('.search-button').click(function(){

$('.search-form').toggle();

return false;

});

$('.search-form form').submit(function(){

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

data: $(this).serialize()

});

return false;

});

$(document).on('click','#user-grid a.delete',{'code':'function() {\n\tif(!confirm(\'Are you sure you want to delete this item?\')) return false;\n\tvar th=this;\n\tvar afterDelete=function(){};\n\t$.fn.yiiGridView.update(\'user-grid\', {\n\t\ttype:\'POST\',\n\t\turl:$(this).attr(\'href\'),\n\t\tsuccess:function(data) {\n\t\t\t$.fn.yiiGridView.update(\'user-grid\');\n\t\t\tafterDelete(th,true,data);\n\t\t},\n\t\terror:function(XHR) {\n\t\t\treturn afterDelete(th,false,XHR);\n\t\t}\n\t});\n\treturn false;\n}'});

jQuery('#user-grid').yiiGridView({'ajaxUpdate':['user-grid'],'ajaxVar':'ajax','pagerClass':'pagination','loadingClass':'grid-view-loading','filterClass':'filters','tableClass':'items table','selectableRows':1,'enableHistory':false,'updateSelector':'{page}, {sort}','pageVar':'User_page','afterAjaxUpdate':{'code':'function() {\r\n\t\t\tjQuery(\'.popover\').remove();\r\n\t\t\tjQuery(\'a[rel=\"popover\"]\').popover();\r\n\t\t\tjQuery(\'.tooltip\').remove();\r\n\t\t\tjQuery(\'a[rel=\"tooltip\"]\').tooltip();\r\n\t\t}'}});

jQuery('#collapse_0').collapse({'parent':false,'toggle':false});

});

/*]]>*/

</script> 



@Maurizio: JS is enabled and everything else on the page is working fine. Sorting the grid, hovering over the buttons - no problem at all.

I set a breakpoint on the line that starts with “$(document).on(‘click’,’#user-grid a.delete’…” but it doesn’t get hit when clicking the button.

Any other ideas on how I could trace this down?

I suppose that wouldn’t get hit when clicking the button as it’s just run once at the initial page setup, to attach the event.

Try writing your function in the same way as softark, as an anonymous function, rather than the serialized text that you’ve created. I imagine you could then set a break point within that function to determine if it was fired.

I just noticed something very strange in your code above… the line where the click event is binded for the delete does have "\n\t" in it. This should be a newline and a tab and not a literal "\n\t"

True. It’s in single quotes, so won’t be interpolated by the parser.

EDIT: My mistake, it’s js not PHP code.

But the corrupt portion of the scripts should have been generated by Yii … maybe by CGridView or CButtonColumn. The corruption should not happen usually.

I don’t know what’s happening.

Well that makes two of us then :D

As softark said, the whole code is generated by Gii, didn’t write any of it myself.

I’m using Yii 1.1.12 and the “Yii Bootstrap 1.0” extension. Don’t think the later has any say in this though, the “bootstrap.widgets.TbGridView” and “zii.widgets.grid.CGridView” generate the exact same code (as posted above).

Any ideas on where to look for what’s going wrong? Don’t have a lot of experience with JS.

I would suggest you to create a new plain webapp with Yii and then a new CRUD for any table of yours… then check if the same "problem" happens there.

I had a look at the source for CButtonColumn. There is a function "registerClientScript", looks like this:




        /**

	 * Registers the client scripts for the button column.

	 */

	protected function registerClientScript()

	{

		$js=array();

		foreach($this->buttons as $id=>$button)

		{

			if(isset($button['click']))

			{

				$function=CJavaScript::encode($button['click']);

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

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

			}

		}


		if($js!==array())

			Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$this->id, implode("\n",$js));

	}



The line “$function=CJavaScript::encode($button[‘click’]);” causes the “messed up” result. When I change it to “$function=$button[‘click’];”, everything works like a charm with the delete buttons fully functional.




        /**

	 * Registers the client scripts for the button column.

	 */

	protected function registerClientScript()

	{

		$js=array();

		foreach($this->buttons as $id=>$button)

		{

			if(isset($button['click']))

			{

				//$function=CJavaScript::encode($button['click']);

                                $function=$button['click'];

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

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

			}

		}


		if($js!==array())

			Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$this->id, implode("\n",$js));

	}



Is there any harm to using this "fix"?

That call is encoding a PHP variable value into javascript rapresentation so it should not be removed… and it does not explain why this is happening only to you.

Can you please debug further to see what in the encode() method is causing that problem to you?

Oh… .I traced a bit that code… and remembered we had some problems with the CJavascriptExpression::__toString()… could that be the problem here, too

Do you use PHP 5.1, if yes there was a problem with it that is already fixed in the trunk, check this issue - https://github.com/yiisoft/yii/pull/1096

The server is running PHP 5.3.13. I’ll have a look at the “encode()” method.

Ok this is embarrassing - for whatever reason my CJavaScript.php was still on Version 1.1.10, while all the other files had been updated to 1.1.12. Thus CButtonColumn used the CJavascriptExpression but that class was not recognised by CJavaScript.

It’s all working fine now, thanks for your help guys.