Modify the delete function in CGridView

Hello,

how to delete modify or replace this function which is created automatically ?




jQuery('#client-grid a.delete').live('click',function() {

	if(!confirm('Voulez-vous vraiment supprimer cet élément ?')) return false;

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

		type:'POST',

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

		success:function() {

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

		}

	});

	return false;

});



[s]Then tell us what you really want? :] Delete this function (i.e. disable delete button) or change how it works (and why - it works fine)? :]

There are many, easy methods of disabling or changing delete button (and others), please take a look to this article for more information. But if you would like to change how exactly delete jQuery function works, then this is a harder task. I don’t recall anyone else needing such change and I don’t see any other solution than extending CButtonColumn with own class and changing delete function there.[/s]

EDIT: Well, once again Antonio is right, and provided a better solution! :]

Hi there Mahdl,

In CGridView configuration, this way:

‘class’=>‘CButtonColumn’,

‘buttons’=>array(

‘delete’=>array(‘click’=>‘js:yournewjsfunction’),

)

Check the code of CButtonColumn, line 149. That piece of code is set on initDefaultButtons function, after that it checks if its ‘click’ event for every button ID is set.

Yes I want to change the method of removal used, I want to add more lines of code in this function

I tried this test, but nothing has been changed




		'class'=>'CButtonColumn',

		'template'=>'{delete}',

		'buttons'=>array(

				'delete'=>array(

						'click'=>'js:alert("new function")', 

				),

		),






'click'=>'js:function(){ alert("new function"); }', 



it does not work !!

help please !!

thank you for your answers

Hi Mahdl,

Then I suggest you extend from CButtonColumn, and overwrite the renderButton function my friend…

And if you wish to have more control, then even initDefaultButtons function…

edit:

You are right, the initDefaultButtons overwrites initial settings and by default it sets the delete action… so, we need to extend CButtonColumn and rewrite the initDefaultButtons for our needs.

create a class that extends from CButtonColumn:




class MyCustomButton extends CButtonColumn{

    // overwrite just one function for your needs

   /**

	 * Initializes the default buttons (view, update and delete).

	 */

	protected function initDefaultButtons()

	{

		if($this->viewButtonLabel===null)

			$this->viewButtonLabel=Yii::t('zii','View');

		if($this->updateButtonLabel===null)

			$this->updateButtonLabel=Yii::t('zii','Update');

		if($this->deleteButtonLabel===null)

			$this->deleteButtonLabel=Yii::t('zii','Delete');

		if($this->viewButtonImageUrl===null)

			$this->viewButtonImageUrl=$this->grid->baseScriptUrl.'/view.png';

		if($this->updateButtonImageUrl===null)

			$this->updateButtonImageUrl=$this->grid->baseScriptUrl.'/update.png';

		if($this->deleteButtonImageUrl===null)

			$this->deleteButtonImageUrl=$this->grid->baseScriptUrl.'/delete.png';

		if($this->deleteConfirmation===null)

			$this->deleteConfirmation=Yii::t('zii','Are you sure you want to delete this item?');


		foreach(array('view','update','delete') as $id)

		{

			$button=array(

				'label'=>$this->{$id.'ButtonLabel'},

				'url'=>$this->{$id.'ButtonUrl'},

				'imageUrl'=>$this->{$id.'ButtonImageUrl'},

				'options'=>$this->{$id.'ButtonOptions'},

			);

			if(isset($this->buttons[$id])){

				$this->buttons[$id]=array_merge($button,$this->buttons[$id]);

			}

			else

				$this->buttons[$id]=$button;

		}


		if(is_string($this->deleteConfirmation))

			$confirmation="if(!confirm(".CJavaScript::encode($this->deleteConfirmation).")) return false;";

		else

			$confirmation='';


		if(Yii::app()->request->enableCsrfValidation)

		{

	        $csrfTokenName = Yii::app()->request->csrfTokenName;

	        $csrfToken = Yii::app()->request->csrfToken;

	        $csrf = "\n\t\tdata:{ '$csrfTokenName':'$csrfToken' },";

		}

		else

			$csrf = '';


          // HERE IS WHERE IT OVERWRITES YOUR DELETE CLICK SETTING!

         // WE COULD DO THIS

         if(isset($this->buttons['delete']) && isset($this->buttons['delete']['click'])) return;


         // NOT SET CONTINUE 

		$this->buttons['delete']['click']=<<<EOD

function() {

	$confirmation

	$.fn.yiiGridView.update('{$this->grid->id}', {

		type:'POST',

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

		success:function() {

			$.fn.yiiGridView.update('{$this->grid->id}');

		}

	});

	return false;

}

EOD;

	}

}




After that, specify this class on your CGridView instead of CButtonColumn and set its ‘delete’ button as specified before.

Or you can just use a custom button… - http://www.yiiframework.com/doc/api/1.1/CButtonColumn#buttons-detail

You mean that we can do a ‘mycustomdeletebutton’ and set its properties?

Didnt know that, is a better solution… thanks mdomba

Well that isn’t truly “custom delete button”! :] It’s just any button and for the particular one you are writing a delete behaviour, different than original one and in the same time you are hiding original delete button. In result, you got so called custom delete button, but of course (and as you probably know) this custom button can be used for virtually any purpose - voting, selecting something etc.

For people interested in more reading about customising buttons in CButtonColumn I kindly propose my own wiki text about it.

Thank you all for your answers :)

I used this property, but it does not work !!

Here is my code :




		array(

			'class'=>'CButtonColumn',

			'template'=>'{view}{update}{delete}',

			'buttons'=>array(

					'view'=>array(

							'imageUrl'=>'images/view.png',					

						),

					'update'=>array(

							'imageUrl'=>'images/update.png',					

						),

					'delete'=>array(

							'imageUrl'=>'images/delete.png',

							'click'=>'function(){alert("Delete button");}',

					),

			),

		),




{delete} in template is reserved for the Yii delete button…

you need to use something other like {mydelete} the same for the buttons array…

Thank you very much. it works :)

It’s such a shame that $data->id is not availabe in the body of the js function for the click option of the custom button.

I need to do an ajax POST and I need the data id in the js function.

$data is evaluated by PHP while rendering the page (server side)… javascript code is run after that while the users are entering some values on the page (client side)…

that’s why you cannot have $data->id in the javascript code… but you can read the value from the page if you put it somewhere (in a column maybe)…

check this topic for some ideas - http://www.yiiframework.com/forum/index.php?/topic/13804-

I came up with a solution that has been working for me, although I think if you need to do this in multiple locations extending CButtonColumn and modifying the initDefaultButtons method and adding a beforeDelete parameter alongside the afterDelete one is a better solution. This works if you just want to do it quickly in one location.




"click"=>"function(){

  if(!confirm('Are you sure you wish to remove this item?'))

    return false;

  var th = this;

  var beforeDelete = function(){

    //whatever you want to do before the ajax call is sent

  };

  var afterDelete = function(link,success,data){

    //whatever you want to do after the ajax call returns

  };

  beforeDelete();

  $.fn.yiiGridView.update(

    '$GridViewID',

    {

      type:'POST',

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

      ".(Yii::app()->request->enableCsrfValidation?"data:{'".Yii::app()->request->csrfTokenName."':'".Yii::app()->request->csrfToken."'},":'')."

      success:function(data){

        $.fn.yiiGridView.update('$GridViewID');

        afterDelete(th,true,data);

      },

      error:function(XHR){

        return afterDelete(th,false,XHR);

      }

    }

  );

  return false;

}"

I basically duplicated exactly what initDefaultButtons was doing with the information passed in minus one thing. since we can’t evaluate the widget’s ID at this point (or at least I know no way of doing so) the ID must be set manually. You’ll see 2 locations I reference $GridViewId inside my click function, this needs to be set on the widget for this to work.

When using this function, the afterDelete and deleteConfirmation properties will not be used for anything. instead you must modify the code I’ve provided and add those things in yourself. I only added in the beforeDelete definition before calling it for ease of reading, if you prefer you can just write in the code you want to execute.