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

21 followers

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

Total 7 comments

#13048 report it
dhanakumar at 2013/04/30 09:42am
need help

hi ,

i need to help this same as for update action .. please help me

#8599 report it
Gerhard Liebenberg at 2012/06/13 05:11pm
ID

Very cool:

Just, remember to change "ID" to your own primary key in Part 1:

Step 1 -> CGridView view button -> 'url'
and
Step 3 -> beginWidget -> 'id' and 'title'

#8523 report it
bonnie at 2012/06/10 09:35am
Thanks for this tutorial

Thanks for this tutorial but have few issues as am trying to use a normal chtml::link to achieve this feature in my app. Here is the code am trying to modify

<?php echo CHtml::link('View', 
array(
'url'=>'Yii::app()->createUrl("//backoffice/user/show", array("id"=>$model->id,"asDialog"=>1))',
'options'=>array(
'ajax'=>array(
'type'=>'POST',
//ajax post will use 'url' specified above 
'url'=>"js:$(this).attr('href')", 
'update'=>'#id_view',
),
),
)
);
?>

The above link when clicked on does not go anywhere I understand this feature was done with CButtonColumn but in my app am using normal links because I have my own gridview different from what yii uses by default. Help please.

#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
Peter JK 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.

Write new article
  • Written by: Joblo
  • Category: Tips
  • Yii Version: 1.1
  • Votes: +15
  • Viewed: 31,159 times
  • Created on: Oct 21, 2011
  • Last updated: Jun 19, 2012
  • Tags: CGridView, CJuiDialog