Create A Dynamic Cgridview

Here are some snippets to help you create user adaptable gridviews. This is especially useful with large tables. You could modify this approach to display different default/available columns for different users.

This will modify models, controllers, and views generated with Gii model and crud generator.

Let’s assume that the model name is MyModel.




CREATE TABLE `my_model` (

  `id` INT NOT NULL AUTO_INCREMENT ,

  `name` VARCHAR(45) NULL ,

  `email` VARCHAR(45) NULL ,

  `phone` VARCHAR(45) NULL ,

  `birthday` DATE NULL ,

  `about` TEXT NULL ,

  `username` VARCHAR(45) NULL ,

  `password` VARCHAR(45) NULL ,

  `secret` VARCHAR(45) NULL ,

  `active` TINYINT(1) NULL ,

  PRIMARY KEY (`id`) );



Hopefully the comments in the code will explain enough to get your through.

First, create a file called views/myModel/_fields.php an place the following:




<?php

/* @var $this MyModelController */

/* @var $model MyModel */

/* @var $form CActiveForm */

?>


<div>


<?php $form=$this->beginWidget('CActiveForm', array(

	'id'=>'my-model-columns',

	'enableAjaxValidation'=>false,

));


$modelColumns=$model->getMetaData()->columns;

$attributeLabels = $model->attributeLabels();




$i=0;

foreach ($modelColumns AS $column => $columnData) {

    

    // group fields into columns for big tables (optional)

    if ($i==0) {

        echo '<div style="float:left">';

    }

    

    // set selected columns to be checked

    $checked=0;

    if (in_array($column,$columns)) {

        $checked=1;

    }


    // restrict sensitive columns that should not be viewed or searched

    if ($column!='password' && $column!='secret') {

            echo CHtml::checkBox("columns[]",$checked,array('value'=>$column,'id'=>"column_$column"));

            echo CHtml::label($attributeLabels[$column],"column_$column");

            echo "<br/>\r\n";

    }


    // group columns

    $i++;

    if ($i==10) {

        echo '</div>';

        $i=0;

    }

}

// group columns

if ($i!==0) {

    echo '</div>';

}

?>

	<div class="row buttons clear">

		<?php echo CHtml::submitButton('Refresh'); ?>

	</div>


<?php $this->endWidget(); ?>


</div><!-- form -->



Now lets modify the view (views/myModel/admin.php):




<?php

/* @var $this MyModelController */

/* @var $model MyModel*/


$this->breadcrumbs=array(

	'MyModel'=>array('index'),

	'Manage',

);


$this->menu=array(

	array('label'=>'List MyModel', 'url'=>array('index')),

	array('label'=>'Create MyModel', 'url'=>array('create')),

);


Yii::app()->clientScript->registerScript('search', "

$('.search-button').click(function(){

	$('.search-form').toggle();

	return false;

});

// add the script to toggle the field list

$('.fields-button').click(function(){

	$('.fields-form').toggle();

	return false;

});

$('.search-form form').submit(function(){

	$('#application-grid').yiiGridView('update', {

		data: $(this).serialize()

	});

	return false;

});

");

?>


<h1>Manage MyModel</h1>


<p>

You may optionally enter a comparison operator (<b>&lt;</b>, <b>&lt;=</b>, <b>&gt;</b>, <b>&gt;=</b>, <b>&lt;&gt;</b>

or <b>=</b>) at the beginning of each of your search values to specify how the comparison should be done.

</p>


<?php echo CHtml::link('Advanced Search','#',array('class'=>'search-button')); ?>

<div class="search-form" style="display:none">

<?php $this->renderPartial('_search',array(

	'model'=>$model,

)); ?>

</div><!-- search-form -->


<!-- create a link to show the fields and load the field view -->

<?php echo CHtml::link('Customize Fields','#',array('class'=>'fields-button')); ?>

<div class="fields-form" style="display:none">

<?php $this->renderPartial('_fields',array(

	'model'=>$model,

	'columns'=>$columns,

)); ?>

</div>


<?php

// here we create an array of columns for the grid view

$modelColumns=$model->getMetaData()->columns;

foreach ($modelColumns AS $columnName => $columnData) {


    if (in_array($columnName,$columns)) {

        $key=array_search($columnName,$columns);

        

        if ($columnData->dbType=='tinyint(1)') {

            // (mysql) if it's set as a boolean, filter with a select

            $columns[$key]=array('name'=>$columnName,'filter'=>array('1'=>'Yes','0'=>'No'),'value'=>'($data->'.$columnName.'=="1")?("Yes")<img src='http://www.yiiframework.com/forum/public/style_emoticons/default/sad.gif' class='bbc_emoticon' alt=':(' />"No")');

        } elseif ($columnData->dbType=='date') {

            //if it's a date field, filter with a date picker

            $columns[$key]=array(

                'name' => $columnName,

                'filter' => $this->widget('zii.widgets.jui.CJuiDatePicker', array(

                    'model'=>$model, 

                    'attribute'=>$columnName, 

                    'language' => 'ja',

                    'i18nScriptFile' => 'jquery.ui.datepicker-ja.js',

                    'htmlOptions' => array(

                        'id' => 'datepicker_for_'.$columnName,

                        'size' => '10',

                    ),

                    'defaultOptions' => array(

                        'showOn' => 'focus', 

                        'dateFormat' => 'yy-mm-dd',

                        'showOtherMonths' => true,

                        'selectOtherMonths' => true,

                        'changeMonth' => true,

                        'changeYear' => true,

                        'showButtonPanel' => true,

                    )

                ), 

                true),

            );

        } elseif (stristr($columnData->dbType,'decimal')) {

            // if it's a decimal, align text to the right

            $columns[$key]=array('name'=>$columnName,'htmlOptions'=>array('style' => 'text-align: right;'));

        } elseif (stristr($columnName,'email')) {

            // if it's an email, link it to the email

            $columns[$key]="$columnName:email";

        }

        // add more custom column types here

    }

}


// add the button column

// set the button column header to be a drop down to select page size

// don't forget to change 'my-model-grid' to reflect your grid 'id'

$columns[]=array(

            'class'=>'CButtonColumn',

            'template'=>'{view}{update}{delete}',

            'header'=>CHtml::dropDownList('pageSize',$pageSize,array(10=>10,20=>20,50=>50,100=>100),array('onchange'=>"$.fn.yiiGridView.update('my-model-grid',{ data:{pageSize: $(this).val() }})")),

);


// display the gridview

$this->widget('zii.widgets.grid.CGridView', array(

	'id'=>'my-model-grid',

	'dataProvider'=>$model->search(),

	'filter'=>$model,

	'columns'=>$columns,

));



So now let’s change action admin in controllers/MyModelController.php





    /**

     * Manages all models.

     */

    public function actionAdmin() {

        $model = new MyModel('search');


        // set the columns to those posted

        if (!empty($_POST['columns'])) {

            // name the cookies after the model or something unique so that other gridviews don't overwrite this one

            unset(Yii::app()->request->cookies['my-model-columns']);  // first unset cookie for columns

            Yii::app()->request->cookies['my-model-columns'] = new CHttpCookie('my-model-columns', serialize($_POST['columns']));  // define cookie for columns

            $columns = $_POST['columns'];

        } elseif (empty(Yii::app()->request->cookies['my-model-columns'])) {

            // if no columns are selected, set the default columns

            // let's assume MyModel has at least id, name, email, phone, birthday (date), and active (boolean)

            $columns = array(

                'id',

                'name',

                'email',

                'phone',

                'birthday',

                'active',

            );

        } else {

            $columns = unserialize(Yii::app()->request->cookies['my-model-columns']);

        }

        

        // page size for the gridview

        $pageSize = Yii::app()->user->getState('pageSize', Yii::app()->params['defaultPageSize']);

        if (isset($_GET['pageSize'])) {

            $pageSize = $_GET['pageSize'];

            Yii::app()->user->setState('pageSize', (int) $_GET['pageSize']);

            unset($_GET['pageSize']);

        }


        $model->unsetAttributes();  // clear any default values

        if (isset($_GET['MyModel']))

            $model->attributes = $_GET['MyModel'];


        $this->render('index', array(

            'model' => $model,

            'columns' => $columns,

            'pageSize' => $pageSize,

        ));

    }




Finally we need to make a minor change to the search method in our model /models/MyModel.php




    public function search() {

        // @todo Please modify the following code to remove attributes that should not be searched.


        $criteria = new CDbCriteria;

        $criteria->with = array('user');


        $criteria->compare('id', $this->id);

        $criteria->compare('name', $this->name, true);

        $criteria->compare('email', $this->email, true);

        $criteria->compare('phone', $this->phone, true);

        $criteria->compare('birthday', $this->birthday, true);

        $criteria->compare('about', $this->about, true);

        $criteria->compare('username', $this->username, true);

        $criteria->compare('active', $this->active);

        

        $criteria->order = 'name';

        

        return new CActiveDataProvider($this, array(

            'criteria' => $criteria,

            // set the page size to the one selected in the grid view

            'pagination' => array(

                'pageSize' => Yii::app()->user->getState('pageSize', Yii::app()->params['defaultPageSize']),

            ),

        ));

    }



Now each user can customize the columns and page size in the gridview.

If you feel ambitious, create some Gii templates and include this on every model and crud you create.

I’ve attached a screenshot of what the result might look like.

4963

cgridview.png

Nice inputs and tips. Thanks.

Nice scripts man :)

THNX FOR THE POST ITZ RELAY USEFULL :rolleyes:

Nice scripts, so usefull, thank a lot ;)

Thanks for that really good post and tips

nice post