Difference between #8 and #9 of CGridView: Display the full record (actionView) in a CJuiDialog

unchanged
Title
CGridView: Display the full record (actionView) 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")
----------------------------------------------------------------------------------------------------------------
 

If you show a model (with a lot of attributes) partially in a CGridView, it can
be helpful when the user can take a quick look at the full record with all
attributes without displaying the view 
as a page and afterwards returning back to the gridview.

It needs only a few steps/changes to change the behavior of the 'view' icon in
the CButtonColumn so that 'actionView' is rendered into a CJuiDialog.
Now the user can open one - or even more - dialog(s) with all record details.

- Assume you have a model 'Address' with the attributes (id, firstname,
lastname, ...)
- You have generated the default model and controller with gii.
- In the gridview you display the id, firstname, lastname, street,  countrycode
and city

**You can implement this in two ways:**

- Allow the user to **open multiple dialogs** to display different records at
once
- **Allow only one dialog** and update the content when the user selects another
record.


Part I: Allow to open multiple dialogs
--------------------------------------

**Step 1**

Add code to the zii.widgets.grid.CGridView to change the behavior of the 'view'
icon.
A click on the icon now will result in an ajax call to /address/view

~~~
[php]
....
<?php $this->widget('zii.widgets.grid.CGridView', array(
	'id'=>'address-grid',
	'dataProvider'=>$model->search(),
	'filter'=>$model,
	'columns'=>array(
		'ID',
		'FIRSTNAME',
		'LASTNAME',
                'STREET', 
		'COUNTRYCODE',
                'CITY',  
		/*
		'ZIPCODE',
		'PROVINCE',
		'EMAIL',
		'PHONE1',
		'PHONE2',
		'FAX',
		'REGION',
		'NOTE',
		...
		*/
		array(
'class'=>'CButtonColumn',
//--------------------- begin added --------------------------
'buttons'=>array('view'=>
array(
	'url'=>'Yii::app()->createUrl("address/view",
array("id"=>$data->ID,"asDialog"=>1))',
	'options'=>array(  
	'ajax'=>array(
			'type'=>'POST',
                // ajax post will use 'url' specified above 
			'url'=>"js:$(this).attr('href')", 
			'update'=>'#id_view',
		   ),
	 ),
	 ),
   ),
//--------------------- end added --------------------------
  ),
  ),
)); 

//----------- add the div below as container for the dialog
-----------------------
?>

<div id="id_view"></div>
~~~

**Step 2**

Change the code of actionView in the AddressController.
If you want to display the output in a dialog (or maybe other ajax area) you
have to use 'renderPartial' instead of 'render'.
You have to set $processOutput=true to render the CJuiDialog js-script too.

Coded this way, it's possible to display the record in a single page or in the
dialog.
~~~
[php]

public function actionView($id)
{
 if (Yii::app()->request->isAjaxRequest) 
  {
	$this->renderPartial('view', array(
								   'model'=>$this->loadModel($id),
								   'asDialog'=>!empty($_GET['asDialog']),
								 ),
						  false,true);
     Yii::app()->end();
   }
 else
	$this->render('view', array(
	   'model'=>$this->loadModel($id),
	 ));
}
~~~

**Step 3**

Change the view-code of the file address/view.php to display the CJuiDialog
widget if $asDialog=true.

~~~
[php]

<?php
//------------ add the CJuiDialog widget -----------------
if (!empty($asDialog)):
	$this->beginWidget('zii.widgets.jui.CJuiDialog', array( // the dialog
		'id'=>'dlg-address-view-'. $model->ID,
		'options'=>array(
		    'title'=>'View Address #'. $model->ID,
		    'autoOpen'=>true,
		    'modal'=>false,
		    'width'=>550,
		    'height'=>470,
		),
 ));
	
else:
//-------- default code starts here ------------------
?>
<?php
$this->breadcrumbs=array(
	'Addresses'=>array('index'),
	$model->NAME,
);

$this->menu=array(
	array('label'=>'List Address', 'url'=>array('index')),
	// ... more operations portlet code generated by gii
);

?>
<h1>View Address #<?php echo $model->ID; ?></h1>

//--------------------- begin added --------------------------
<?php endif; ?>
//--------------------- end added --------------------------

<?php $this->widget('zii.widgets.CDetailView', array(
	'data'=>$model,
	'attributes'=>array(
		'ID',
		'CODE',
		'FIRSTNAME',
		'LASTNAME',
		'STREET',
		'ZIPCODE',
		'CITY',
		'COUNTRY',
		'COUNTRYCODE',
		'PROVINCE',
		'EMAIL',
		'PHONE1',
		'PHONE2',
		'FAX',
		'REGION',
		'NOTE',
		//... all record attributes
	),
)); 
//-------- end of default code  ------------------
?>

<?php 
  //----------------------- close the CJuiDialog widget ------------
  if (!empty($asDialog)) $this->endWidget();
?>

~~~


Part II: Allow only a single dialog
----------------------------
The user can drag the dialog to a postion he likes. 
Update the content of the dialog on every 'view-icon' click.
This solutions has a **better performance and no need to change the view.php
code**

Differences compared to Part I:

- Don't render the CJuiDialog in the views/address/view.php. You **don't have to
change the view.php 
generated by gii**. Leave it untouched, **no need for Step 3 from above**.
- Render the CJuiDialog widged in views/address/admin.php below the CGridview
and set **'autoOpen'=>false**
- Open the dialog by rendering the js-code
**'$("#dlg-address-view").dialog("open")'** in the
actionView.

**Step 1**

The admin.php code.

~~~
[php]
....
<?php $this->widget('zii.widgets.grid.CGridView', array(
	... CGridview the same as above ...
)); 

//the dialog
$this->beginWidget('zii.widgets.jui.CJuiDialog', array( 
'id'=>'dlg-address-view',
'options'=>array(
    'title'=>'Detail view',
    'autoOpen'=>false, //important!
    'modal'=>false,
    'width'=>550,
    'height'=>470,
),
));
?>
<div id="id_view"></div>
<?php $this->endWidget();?>
~~~

**Step 2**
The viewAction code from AddressController. 

- Code to open the dialog

~~~
[php]
public function actionView($id)
{
	if (Yii::app()->request->isAjaxRequest)
	{
		//outputProcessing = true because including css-files ...
		$this->renderPartial('view', 
		    array(
			   'model'=>$this->loadModel($id),
			 ),false,true);
		//js-code to open the dialog	
          if (!empty($_GET['asDialog'])) 
		    echo
CHtml::script('$("#dlg-address-view").dialog("open")');
		Yii::app()->end();
	}
	else
		$this->render('view', array(
		   'model'=>$this->loadModel($id),
		 ));
}
~~~


Tips
---

- Without using the CJuiDialog you can **show the records below the grid**.
- You can use this techniqe to **show master records in the grid and detail
records below or in a dialog** too. You only have to set the correct url /
action in the CGridView.



**Similar and other useful articles**

-
[using-cbuttoncolumn](http://www.yiiframework.com/wiki/106/using-cbuttoncolumn-to-customize-buttons-in-cgridview/
"Using CButtonColumn")
-
[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/
"") 
-
[cjuidialog-and-ajaxsubmitbutton](http://www.yiiframework.com/wiki/72/cjuidialog-and-ajaxsubmitbutton
"")