Trying To Understand How Ajax Forms In A Cgridview Work

Hi,

I have a view containing a CGridView widget and a custom form.

When I use some of the built-in tools for the CButtonColumn, like the ‘delete’ button, I trigger an AJAX request that re-renders the specified view. So far so good.

Or almost: I noticed that the ‘delete’ button triggers $.fn.yiiGridView.update(), which apparently sends another request AFTER the delete request, to update the grid view. Why two requests?

But my main problem is that I’m trying to update the grid with a simple form, outside of the gridView, which adds an element to the list. This is how my partial view looks like, wrapped in a div with id ‘task_data’:


<div class="form">


<?php $form=$this->beginWidget('CActiveForm', array(

	'id'=>'task-form',

	'action'=>Yii::app()->createUrl('task/addToBatch'),

)); ?>

	<?=$form->errorSummary(Task::model())?>


	<div class="row">

		<strong>Add a task: </strong>

		<?=$form->hiddenField(Batch::model(),'id',['value'=>$bid])?>

		<?=$form->dropDownList(Task::model(),'id',['']+Task::model()->listActive)?>

		<?=$form->error(Task::model(),'id')?>

		<?=CHtml::ajaxButton('Add',Yii::app()->createUrl('task/addToBatch'),[

			'update'=>'#task_data',

			'type'=>'POST',

		])?>

	</div>


<?php $this->endWidget('Add'); ?>


</div><!-- form -->


<CGridView widget code...>




This sends the correct request, which modifies some records and renders a partial view with the grid and form.

But the returned data includes links to JS library files already there, including additional onLoad functions for the delete buttons. Therefore, when I press the ‘delete’ button after submitting the form, it triggers the ‘Are you sure?’ dialog and the ajax request multiple times.

I noticed that the asset files linked in the request have a timestamp added to their URL, such as

.../assets/a8048f13/gridview/jquery.yiigridview.js?_=1361917741284 so they are forced to be reloaded.

How can I avoid to re-load the external JS files and to re-register the grid AJAX functions? Do I necessarily have to use $.fn.yiiGridView.update() as a callback in order to re-load the js correctly?

Thanks,

gm

Hello, what I perceive from your question are :

  1. Multiple ajax request

  2. Multiple jquery registered

Am I correct ?

If so, regarding to multiple ajax request, have you checked this wiki ?

And to avoid the jquery to be registered multiple times, I think you could disable the jquery in your controller action which is called by the ajax method :




...

public function actionAjax() {

   ...

   Yii::app()->clientScript->scriptMap['jquery.js'] = false;

   Yii::app()->clientScript->scriptMap['jquery.min.js'] = false;

   ...

}

...



Or you may take a look at this extension and this post also

Setting processOutput to false worked. Thanks! I didn’t need to un-map the library files, and I’m glad I didn’t have to since I have more than one.

It’s nice to know that you can still initiate JS by hardcoding it into the page, e.g.

(view code)


<?php Yii::app()->clientScript->registerScript('test', 'alert("This is processed by Yii")');?>


<script type="text/javascript">

	alert("This is not processed by Yii");

</script>



The first message will only appear if the action renders the view with the processOutput option turned on (note: AFTER the second one); the second one executes always.

As for your #1 - I didn’t formulate my question at its best since I mixed up two different topic. My first question was: why is the delete button from CButtonColumn trigger two requests, one for deleting and one for refreshing the grid?

Did you make any changes to the actionDelete in your controller ? If not, then by default the delete action method in the controller is triggered by AJAX method and therefore it will refresh the grid on delete action.




public function filters() {

       return array(

		'accessControl', // perform access control for CRUD operations

		'postOnly + delete', // we only allow deletion via POST request

	);

}


public function actionDelete($id) {

	$this->loadModel($id)->delete();


	// if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser

	if(!isset($_GET['ajax']))

		$this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('admin'));

}



As you can see, if the request is AJAX request, which is by default will be triggered by deletion via admin grid view, it will not redirect the page and instead it will refresh the grid.