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

13 followers

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>
 
<?php endif; ?>
 
<?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

Total 4 comments

#7508 report it
Cheooc at 2012/03/27 01:56am
nothing displays

I have read topic and did the same. But when i click on {view} icon ,nothing displays. Help me :(

#7493 report it
yiimike at 2012/03/26 07:13am
Firefox 11.0 note

Re part 1, In FF 11, think u need to add this to the div:

<div id="id_view" style="display:none;"></div>

to stop the div flickering, Chrome seems ok though.

#7245 report it
kkkyka6s at 2012/03/06 12:20pm
works like a charm...

Thanks, works perfect. The only problems I had was the uppercase ID in the admin.php:

array("id"=>$data->ID...

This lead to a total cofused page admin.php, where an error is on the left.

Now it works!

#6282 report it
peterjkambey at 2011/12/24 09:43am
thank you

thank you, joblo...

nice and helpful article... very useful in office application that have too many fields..

Leave a comment

Please to leave your comment.