Handling Auto Generated Ajax Delete Buttons

I have a list that is populated and next to each item a remove button is generated. The remove button sends the current list of items and the key id that is to be deleted. It works and then it doesn’t. Sometimes it’ll delete the right item, sometimes it won’t delete the item and rather just changed the displayed item values and sometimes it’ll even add an item. Eventually if I click enough they’ll add disappear.

This is a simplified version of what I want to do, but the problem is still visible.

View:


<div id="display"></div>

<?php $items=array(1,2,3,4); ?>

<?php echo CHtml::ajaxButton('Add List',array('AddItem'),array('update'=>'#display','type'=>'POST','data'=> array('items'=>$items))); ?>

_list:


foreach ($items as $key=>$item)

{

	echo $item . CHtml::ajaxButton('Remove',array('RemoveItem'),array('update'=>'#display','id'=>uniqid(),'type'=>'post','data'=>array('id'=>$key,'items'=>$items))) . '<br />';

}

Controller:


public function actionAddItem()

    {

		$data['items']=$_POST['items'];

		$this->renderPartial('_list',$data,false,true);

    }

	public function actionRemoveItem()

    {

		$key=$_POST['id'];

		$items=$_POST['items'];

		unset($items[$key]);

		$data['items']=$items;

		$this->renderPartial('_list',$data,false,true);

    }

I’ve read about generated ajax buttons and links on top of existing forms causing problems. I’ve tried all the solutions I could dig up, but it’s still not working consistently. I feel that all the data being passed is correct and the remove better is also correct, but it’s something with ajax I just don’t understand yet. How would you fix this problem? It’d be nice for users to be able to delete from a list using ajax. Thanks!

Any thoughts on this? I’m still not able to get around it the way I’d like.

this is ajax inside ajax update region problem.

to remove use link(ajaxlink) ,

look this http://www.yiiframework.com/forum/index.php/topic/35912-chtmlajaxlink-with-yiiapp-request-geturl/page__st__20

this

use link with ajax , like that script says.

in _list add


Yii::app()->clientScript->registerScript('ajax-link-handler', "

$('#display a').live('click', function(event){

        $.ajax({

                'type':'get',

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

                'dataType': 'html',

                'success':function(data){

                        $('#display').html(data);

                }

        });

        event.preventDefault();

});

");




foreach ($items as $key=>$item)

{

        echo $item . CHtml::link('Remove',array('RemoveItem','id'=>$key,'items'=>$items),array('id'=>uniqid())) . '<br />';

}

Well, in fact, I’m a bit hesitant to tell my thought about this matter, but …

In general, creating an ajax function inside the ajax updated region is challenging … it could be sometimes very complicated, or cumbersome at the very least.

And, there are 2 different approaches to this issue.

[list=1]

[*]Returning HTML + script in ajax response

[*]Returning HTML only in ajax response

[/list]

If you are going to use CHtml::ajaxButton or CHtml::ajaxLink in the partial view script that is rendered as the ajax response, then you are taking the 1st approach.

In this case, you have to set the 4th parameter of renderPartial ($processOutput) to true when responding to ajax call. It will add the script in the response, otherwise it will only return the HTML part.

And, the problem about this approach is that the newly sent scripts can interfere with the already existing scripts in the client browser. You can find a varieties of tips to avoid this problem in forum posts and wikis out there.

On the other hand, if you are taking the 2nd approach, then you should not use CHtml::ajaxXXX in the partial view script that you use for the response, and renderPartial should be called with the 4th parameter set to false (this is the default).

In this case, all the script that you will need later should be initially sent all at once to the client browser when the page is loaded. Writing such a script may seem difficult at a first glance, but it’s usually possible using jQuery.on() … I’m afraid not always, but usually.

IMO, the 2nd approach should be tried first because of its cleanness.

I don’t know if it helps you directly in your current task, but I think it’s worth examining how the “delete” button function of CGridView is implemented.

The following script is for "delete" function of CGridView. If you are using a "delete" button in the grid, then Yii will automatically add this fragment to your output. (Check the HTML output of some gii-generated "admin" page).




$(document).on('click','#my-grid 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('my-grid', {

		type:'POST',

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

		data:{ 'YII_CSRF_TOKEN':'dbeedff17c0ebeac9533c7b0755ec46141751f4c' },

		success:function(data) {

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

			afterDelete(th,true,data);

		},

		error:function(XHR) {

			return afterDelete(th,false,XHR);

		}

	});

	return false;

});



This code fragment is sent only once to the browser when the page is initially loaded.

As you know, the "delete" button fires an ajax call, and the grid that holds the button is updated by ajax, and the button will not lose its function after the ajax update.

This functionality of "delete" button is implemented with the 2nd approach.

And, I should add that deleting should be done via POST, not via GET.