Multiple Delete Confirmations with CGridView Delete Button

I have a page with CGridView that needs to be refreshed via Ajax request. However, when I click delete button in CGridView after the page is refreshed, I always get multiple delete confirmations. If I use:


$('#category-detail-grid a.delete').die('click');

after Ajax refresh, then the confirmation dialog will only appear once, but delete button will become a common link. Page will be redirected to delete page and an exception will be thrown:


Invalid request. Please do not repeat this request again.

Is there a way to make the confirmation dialog only appears once and doesn’t become a common link after Ajax refresh?

Standars CGridView code generated by Gii works… and it uses AJAX to refresh the view on sorting/filtering

so it should be something in your code… how do you "refresh" with ajax…

Thanks for replying, mdomba. Anyway, here what I do:

I have 2 parts (models) in category page. The main part (form) and detail part. Category detail part consists of several information and CGridView to display data that related to main category. Users can add detail items via form that is rendered in CJuiDialog. After data is saved, dialog should be automatically closed and the detail part of page should be refreshed (via Ajax).




<h1>Update Category</h1>

<?php echo $this->renderPartial('_form', array('model'=>$model)); ?> // this is the main form


<div id="category-detail">  // detail part

    <?php $this->renderpartial('/categoryDetail/create', array('model'=>$detailModelCreate)); ?>

</div>



In view categoryDetail/create :




<?php

// CGridView is rendered in this view

$this->renderpartial('/categoryDetail/admin', 'model'=>$model);


$this->beginWidget('zii.widgets.jui.CJuiDialog', array('id'=>'distributorFormDialog'));

?>

   <div id="divForForm">

       <?php $this->renderpartial('/categoryDetail/_form',array(

	    'model'=>$model, 

	    'categoryId'=>$categoryId

       )); ?>

   </div>

<?php $this->endWidget('zii.widgets.jui.CJuiDialog'); ?>


<script type="text/javascript">

// refresh detail page

function refreshDetail() {

    <?php echo CHtml::ajax(array(

	'url'=>array('categoryDetail/create', 'categoryId'=>$categoryId),

	'update'=>'#category-detail',

  ))?>;

}

</script>



Finally, here is how ajax submit button looks in ‘categoryDetail/_form’:




echo CHtml::ajaxSubmitButton(	'Add', $url, array(	

	'success'=>'js: function(data)  {					

		if (data == "Success")  {

		    // close dialog and refresh detail page if data is successfully saved

		    $("#distributorFormDialog").dialog("close");

		    refreshDetail();

		}

		else

		   // display the form if validation failed

                   $("#divForForm").html(data);

        }'

    ),

    array('id'=>'addItem' .uniqid())

); 		



Besides the delete confirmation that appears twice, I also notice that CJuiDialog cannot be closed after Ajax refresh. Perhaps I do something wrong here?

P.S. I’m sorry if this becomes a long post :blink: , but I’ve truncated them as much as I can.

Problem is that on every refresh you are processing the GridView output and this way adding a new delete handler… so that on every refresh you get another delete handler and delete confirmation…

Check renderPartial - http://www.yiiframework.com/doc/api/1.1/CController#renderPartial-detail

The first time you can call it like now… but on AJAX call try with the 4th parameter set to false…

or a much harder solution… do not refresh that part but use jQuery to empty the input fields… and $fn.yiiGridView.update() to update the grid…

Yes, on AJAX call I set the 4th parameter to true, since there is CJuiDialog and CJuiSliderInput inside ‘category-detail’ div. Anyway, I have moved them out of that div and the dialog confirmation works fine now. Thanks for your really useful suggestion, mdomba.

One more question, please :rolleyes: , the CJuiDialog still cannot be closed after


 $("#divForForm").html(data); 

(in Ajax submit button) is called. This code is called when form validation fails; however, $(‘#distributorFormDialog’).dialog(‘close’) doesn’t seem to be working even data is successfully saved after that.

Should I replace it with something else?

Can’t help you for the second problem as I have not used dialogs until now… for this some debugging is needed to see what is happening and why is not working…

Ok, thanks again for your time, mdomba. I really appreciate your help ::) .

What makes me wonder is whenever


$("#divForForm").html(data);

is not called (no input error in form), the dialog can be closed normally.

#divForForm is the container of the dialog… and you are replacing all it’s content with that line…

but to see what is happening and why the dialog cannot be closed some debugging is needed ;)

Solved via this thread:

http://www.yiiframework.com/forum/index.php?/topic/12011-nested-juidialogs-using-ajaxlink/

Can’t find another way except preventing ajax responses to send down javascript files :( .

had the same issue

this solved it:




Yii::app()->clientScript->registerScript('die click', '

	      jQuery(function(){

	      	jQuery(\'#tableView a.delete\').live(\'click\');

		 });

		', CClientScript::POS_END);



sorry, this should help, but cant make it help…

the trillion confirms stopped because of some jquery error

I understand now why it is not working…

this is why:

http://www.alfajango.com/blog/exploring-jquery-live-and-die/


So there is no good solution for this…

If you load with ajax a lot of CGridViews you should turn of render and load the script yourself or something…

I added different id to every grid, it help a little bit but not a lot…

issue finally solved

in CButtonColumn replace




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



with




$js[]="if(jQuery('body').attr('deleteEventIsset') !== 'yes'){jQuery('body').attr('deleteEventIsset', 'yes');jQuery('#{$this->grid->id} a.{$class}').live('click',$function);}";



if you dont want to hack the core, just extends it and replace the method registerClientScript

It’s a good approach to the issue, but will not work with multiple grids in the same page, because the first grid will allocate the event handler and the following grids will not.

This situation can be easily solved with something like this:

$js[]=“if(jQuery(‘body’).attr(’{$this->grid->id}deleteEventIsset’) !== ‘yes’){alert(‘setting…’);jQuery(‘body’).attr(’{$this->grid->id}deleteEventIsset’, ‘yes’);jQuery(’#{$this->grid->id} a.{$class}’).live(‘click’,$function);}”;

Exactly what I needed. I made a single page app (with the JQuery Pjax plugin) and on every load a new event handler was attached. This is the most elegant solution. Any reason this should not be added to the core?

thx also from my side. i also used the code from jpablo in my application.

with a small change that i use the id of the button so its also working for other buttons with confirm and not only for deleteEventIsset.


 $js[]="if(jQuery('body').attr('{$this->grid->id}{$id}EventIsset') !== 'yes'){jQuery('body').attr('{$this->grid->id}{$id}EventIsset', 'yes');jQuery('#{$this->grid->id} a.{$class}').live('click',$function);}";