Difference between #7 and #8 of CGridView: Update/create records in a CJuiDialog

unchanged
Title
CGridView: Update/create records in a CJuiDialog
unchanged
Category
Tips
unchanged
Tags
CGridView, CJuiDialog
changed
Content
Note:> This code is now part of the extension
[quickdlgs](http://www.yiiframework.com/extension/quickdlgs/
"quickdlgs")
----------------------------------------------------------------------------------------------------------------




My article [Display the full record in a
CJuiDialog](http://www.yiiframework.com/wiki/262/cgridview-display-the-full-record-actionview-in-a-cjuidialog/
"cgridview-display-the-full-record-actionview-in-a-cjuidialog") uses
ajax to view a record in dialog on clicking the 'view-icon'.

Other authors use ajax too for update/insert:

-
[update-delete-model-with-cjuidialog-works-in-cgridview](http://www.yiiframework.com/wiki/216/update-delete-model-with-cjuidialog-works-in-cgridview/
"")
-
[cjuidialog-for-create-new-model](http://www.yiiframework.com/wiki/145/cjuidialog-for-create-new-model/
"") 

Here is a solution that **uses an iframe** within the dialog. It's easy to
implement in a few steps. 

I use the 'Address' example like the one in my last article, but you can
**copy/paste the new code** of views/admin.php and actionUpdate/Create
**unchanged for usage with  any other model**.

### Step 1

You have to generate an iframe-layout (**layouts/iframe.php**) that includes at
least the css-files for the form. You can copy your main-layout and remove
unnecessary code.

**Tip:** You can use this layout to display other content from your site within
a dialog too.

~~~
[php]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de"
lang="de">
<head>
	<meta http-equiv="Content-Type" content="text/html;
charset=utf-8" />
	<meta name="language" content="de" />

	<!-- blueprint CSS framework -->
	<link rel="stylesheet" type="text/css"
href="<?php echo Yii::app()->request->baseUrl;
?>/css/screen.css" media="screen, projection" />
	<link rel="stylesheet" type="text/css"
href="<?php echo Yii::app()->request->baseUrl;
?>/css/print.css" media="print" />
	<!--[if lt IE 8]>
	<link rel="stylesheet" type="text/css"
href="<?php echo Yii::app()->request->baseUrl;
?>/css/ie.css" media="screen, projection" />
	<![endif]-->

	<link rel="stylesheet" type="text/css"
href="<?php echo Yii::app()->request->baseUrl;
?>/css/main.css" />
	<link rel="stylesheet" type="text/css"
href="<?php echo Yii::app()->request->baseUrl;
?>/css/form.css" />
	<link rel="stylesheet" type="text/css"
href="<?php echo Yii::app()->request->baseUrl;
?>/css/custom.css" />

</head>
<body>
<div id="page">
	<?php echo $content; ?>
</body>
</html>
~~~




### Step 2

Alter the code of **views/admin.php**.

You have to add the code for the CJuiDialog and change the behavior of the
CButtonColumn update-icon.

**The click function sets the source for the iframe and opens the dialog.**
It's important to 'return false' onclick.

The 'gridId' is submitted to make the code reusable for other models too.

~~~
[php]
....
<?php $this->widget('zii.widgets.grid.CGridView', array(
	'id'=>'address-grid',
	'dataProvider'=>$model->search(),
	'filter'=>$model,
	'columns'=>array(
		'ID',
		'FIRSTNAME',
		'LASTNAME',
		...
		array(
			'class'=>'CButtonColumn',
			//--------------------- begin new code --------------------------
			'buttons'=>array(
			            'update'=>
			                array(
				               
	'url'=>'$this->grid->controller->createUrl("update",
array("id"=>$data->primaryKey,"asDialog"=>1,"gridId"=>$this->grid->id))',
				               
	'click'=>'function(){$("#cru-frame").attr("src",$(this).attr("href"));
$("#cru-dialog").dialog("open");  return false;}',
								),
			                ),
			//--------------------- end new code --------------------------
		),
	),
));?>


<?php
//--------------------- begin new code --------------------------
   // add the (closed) dialog for the iframe
	$this->beginWidget('zii.widgets.jui.CJuiDialog', array(
	'id'=>'cru-dialog',
	'options'=>array(
	    'title'=>'Detail view',
	    'autoOpen'=>false,
	    'modal'=>false,
	    'width'=>750,
	    'height'=>800,
	),
	));
?>
<iframe id="cru-frame" width="100%"
height="100%"></iframe>
<?php

$this->endWidget();
//--------------------- end new code --------------------------
?>
~~~


### Step 3

Change the code of the **actionUpdate of the controller** like below.
If the get-param 'asDialog' is not set, the method works as usual.

Otherwise:

- The layout is set to '//layouts/iframe'
- After saving the model:
  - Close the dialog
  - Reset the iframe source. Otherwise the last opened record is shown until the
current is loaded. 
  - Refresh the gridview

~~~
[php]
public function actionUpdate($id)
{
	$model=$this->loadModel($id);

	// Uncomment the following line if AJAX validation is needed
	// $this->performAjaxValidation($model);

	if(isset($_POST['Address']))
	{
		$model->attributes=$_POST['Address'];
		if($model->save())
			//----- begin new code --------------------
			if (!empty($_GET['asDialog']))
			{
				//Close the dialog, reset the iframe and update the grid
				echo
CHtml::script("window.parent.$('#cru-dialog').dialog('close');window.parent.$('#cru-frame').attr('src','');window.parent.$.fn.yiiGridView.update('{$_GET['gridId']}');");
				Yii::app()->end();
			}
			else
			//----- end new code --------------------
				
			$this->redirect(array('view','id'=>$model->ADDRESS));
	}

	//----- begin new code --------------------
	if (!empty($_GET['asDialog']))
		$this->layout = '//layouts/iframe';
	//----- end new code --------------------

	$this->render('update',array(
		'model'=>$model,
	));
}
~~~

That's all about updating.


### And what's about the action create?

You can add a link below the caption of the admin-view.


~~~
[php]
<h1>Manage Addresses</h1>

<?php
 $createUrl =
$this->createUrl('create',array("asDialog"=>1,"gridId"=>'address-grid'));
 echo CHtml::link('Create
Address','#',array('onclick'=>"$('#cru-frame').attr('src','$createUrl
'); $('#cru-dialog').dialog('open');"));
?>
~~~

Or you set the 'createUrl' and 'onclick' like above in the operations menu if
you use the default columns2 layout.

The code-snippets from the actionUpdate work unchanged in the actionCreate too.
**Alter the code of actionCreate exactly the same as the code from
actionUpdate** above.


### Tip

Add a **cancel-button** in your **_form.php** in the button row.

~~~
[php]
<div class="row buttons">
		<?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save');
?>
		<?php echo
CHtml::button('Cancel',array('onclick'=>"window.parent.$('#cru-dialog').dialog('close');window.parent.$('#cru-frame').attr('src','');"));
?>
	</div>
~~~

But if you use the update/insert form in single page mode too, you have to check
if the form is shown in the dialog or not, maybe by submitting the variable
'asDialog' to the _form.php.