CGridView: Display the full record (actionView) in a CJuiDialog

  1. Note: This code is now part of the extension quickdlgs
  2. Part I: Allow to open multiple dialogs
  3. Part II: Allow only a single dialog
  4. Tips

Note: This code is now part of the extension 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 $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.

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
//------------ 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 $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
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