CGridView keep state of page and sort.

Remember-filters-gridview is one of the must-use extension on all of my project. However, it lacks of storing the page and sort variables of the grid view.

In addition, Page size dropdown is also useful that I hope some day it can squeeze into the core of the CGridView.

Based on the Page size dropdown, I would like to try to write a wiki on how to store the page and sort variables on the similar way to the Page size dropdown.

First, in your controller (my example is ExtractController), make it like this:

public function actionAdmin() {
        $model = new Extract('search');

        // This is as suggested on the Remember-filter-gridview, 
        // to clear the state of the filter. 
        // I add four line to clear the page and sort as well.
        // Note: somehow, I need to put those lines above the 
        // EButtonColumnWithClearFilters, otherwise, it will not clear the 
        // Extract_page and Extract_sort states.
        if (intval(Yii::app()->request->getParam('clearFilters')) == 1) {
            Yii::app()->user->setState('Extract_page', null);
            unset($_GET['Extract_page']);
            Yii::app()->user->setState('Extract_sort', null);
            unset($_GET['sort']);
            EButtonColumnWithClearFilters::clearFilters($this, $model); //where $this is the controller
        }

        // This portion of code is belongs to Page size dropdown.
        $pageSize = Yii::app()->user->getState('extractPageSize', Yii::app()->params['defaultPageSize']);

        if (isset($_GET['pageSize'])) {
            $pageSize = (int) $_GET['pageSize'];
            Yii::app()->user->setState('extractPageSize', $pageSize);
            unset($_GET['pageSize']);
        }

        // I achieve similar result to Page size with the Extract_page.
        // ELSE body is needed to handle the differences of case back to first page from
        // other pages and call to admin page from anywhere. The ajax method is the key to
        // differentiate it. Call to admin would not be an ajax call, while the call from 
        // pagination is an ajax call (by default. since you can make it non ajax as well).
        if (isset($_GET['Extract_page'])) {
            $extractPage = (int) $_GET['Extract_page'] - 1;
            Yii::app()->user->setState('Extract_page', $extractPage);
            unset($_GET['Extract_page']);
        } else if (isset($_GET['ajax'])) {
            Yii::app()->user->setState('Extract_page', 0);
        }

        // Sort is little bit different. Do not UNSET the sort variable 
        // since it will be directly used by the CGridView.
        // The ELSE body is used to handle non ajax calls to admin page.
        if (isset($_GET['sort'])) {
            $extractSort = $_GET['sort'];
            Yii::app()->user->setState('Extract_sort', $extractSort);
        } else if(Yii::app()->user->hasState('Extract_sort')) {
            $_GET['sort'] = Yii::app()->user->getState('Extract_sort');
        }

        $this->render('admin', array(
            'model' => $model,
            'pageSize' => $pageSize,
        ));
    }

Second, the model (Extract.php). We only need to change the search method :

public function search() {
        $criteria = new CDbCriteria;

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

        $sort = new CSort;
        $sort->defaultOrder = 'name ASC';
        $sort->attributes = array(
            'name' => 'name',
            'productNumber' => 'productNumber',
            'specification' => 'specification',
        );

        $sort->applyOrder($criteria);

        return new CActiveDataProvider($this, array(
                    'criteria' => $criteria,
                    'sort' => $sort,
                    'pagination' => array(
                         // This line below is the only addition made to the model by Page size dropdown.
                        'pageSize' => Yii::app()->user->getState('extractPageSize', Yii::app()->params['defaultPageSize']),
                        // This line below is the only addition made to the model in
                        // choosing the page to be displayed.
                        'currentPage' => Yii::app()->user->getState('Extract_page', 0),
                    ),
                ));
    }

That's all we should do.

Future works The code in actionAdmin is little bit messy to me, can anyone give some feedback to tidy up little bit? In addition, I am a beginner in PHP and Yii!, I don't quite understand the consequences in term of performance and security to store those variables in state.

I admit that this is not purely my idea, but still I would like to share this to get some feedback as well as help others with some problem with me.

5 0
13 followers
Viewed: 35 900 times
Version: 1.1
Category: How-tos
Written by: Daniel
Last updated by: Daniel
Created on: Apr 19, 2012
Last updated: 12 years ago
Update Article

Revisions

View all history