Yii Framework Forum: Create A Dynamic Cgridview - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Create A Dynamic Cgridview Let your users customize the columns and page size in CGridView. Rate Topic: -----

Poll: Will you use this with your project? (11 member(s) have cast votes)

Will you use this with your project?

  1. Yes - I am using this right now! (7 votes [63.64%] - View)

    Percentage of vote: 63.64%

  2. Yes - I will definately use this in the future. (3 votes [27.27%] - View)

    Percentage of vote: 27.27%

  3. Maybe (1 votes [9.09%] - View)

    Percentage of vote: 9.09%

  4. No (0 votes [0.00%])

    Percentage of vote: 0.00%

Vote Guests cannot vote

#1 User is offline   laqrhead 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 24
  • Joined: 12-January 11
  • Location:Kelowna, BC, Canada

Posted 06 December 2013 - 06:59 PM

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"):("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.

Attached File  cgridview.png (35.22K)
Number of downloads: 113
One morning I shot an elephant in my pajamas. How he got in my pajamas, I don't know.
2

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users