>php教程 >php手册 >yii_CGridView_ajax_pagination_and_ajax_sort

yii_CGridView_ajax_pagination_and_ajax_sort

WBOY
WBOY원래의
2016-06-21 08:48:58776검색

本文主要内容:

1, 正常情况下 CGridView 实现 Ajax 分页和排序的原理

2, 分页和排序无法Ajax的情况分析

3, 自定义分页(重写CLinkPager)后如何实现 Ajax 分页和排序

/***

author: php攻城师

http://blog.csdn.net/phpgcs

***/

 

 

[php]  

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

    'id'=>'keyword-grid',  

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

    'cssFile'=>false,  

    'template'=>'{items}

{pager} {summary}
',  

    'pager'=>array('cssFile'=>false),  

    'ajaxUpdate'=>true,  

    'columns'=>array(  

        array(  

            'name'=>'leader_name',  

            'value'=>'$data->event',  

            'header'=>'关键词名称',  

            'headerHtmlOptions'=>array('width'=>'130px'),  

        ), .... ....  

以上代码实现一个常规的 CGridView , 除了 pager 用了自定义的样式。。

 

而在页面的源代码中,我来找出相关的部分:

 

[javascript]  

 

[javascript] view plaincopyprint?

 

/*

jQuery(function($) {  

jQuery('#keyword-grid a.delete').live('click',function() {  

    if(!confirm('确定要删除这条数据吗?')) return false;  

    var th=this;  

    var afterDelete=function(){};  

    $.fn.yiiGridView.update('keyword-grid', {  

        type:'POST',  

        url:$(this).attr('href'),  

        success:function(data) {  

            $.fn.yiiGridView.update('keyword-grid');  

            afterDelete(th,true,data);  

        },  

        error:function(XHR) {  

            return afterDelete(th,false,XHR);  

        }  

    });  

    return false;  

});  

jQuery('#keyword-grid').yiiGridView({'ajaxUpdate':['1','keyword-grid'],'ajaxVar':'ajax','pagerClass':'pager','loadingClass':'grid-view-loading','filterClass':'filters','tableClass':'items','selectableRows':1,'pageVar':'keyword_page'});  

});  

/*]]>*/  

 

 

其中会发现 yii 自动加载了 jquery.ba-bbq.js  &&  jquery.yiigridview.js ,以及2段 代码

其中一段是用来实现  删除 一行数据时 弹出提示框 让用户 确认是否删除 功能 的;

一段是最核心关键的 用于 ajax update grid 的, 也正是这部分 代码 实现了 ajax 的翻页 和 排序。

 

/*********** 我是分割线 *******************************/

 

如果发现 点击了 分页 或者 排序 后,不是ajax 方式的(也就是你可以 在 地址栏 中 看到 每次 请求的常常的 url )

一个要检查的地方:

ajaxUpdate=>'', 这个参数

updateSelector=>'', 这个参数

 

/*********** 我是分割线 *******************************/

 

一般情况下,CLinkPager都无法满足我们的需求,要重写;

而重写我这里提供3种方式:

1, 禁用 CGridView自己的Pager ,在 CGridView 之外 自己写

2, 禁用 CGridView自己的Pager ,重写 CGridView 文件, 将 自己的pager 写在     public function renderItems() 中

3, 配置 CGridView 的 pager 参数。

 

如下是默认的 CLinkPager 的样子

翻页: 

 

现在我们想要如下的Pager 效果

第 31 - 40 条, 共 14546 条  

  上一页 1 2 3 4 5 6 7 8 9 10 下一页  

 

 

/***

author: php攻城师

 

***/

 

先看第1种重写方案:

 

重写 CLinkpager 如下:

[php]  

$this->widget('CLinkPager', array(  

    'header'=>'第 '.($paginationTop->getCurrentPage()*$paginationTop->getPageSize()+1).  

    ' - '.($paginationTop->getCurrentPage()*$paginationTop->getPageSize()+$paginationTop->getPageSize()).  

    ' 条, 共 '.$paginationTop->getItemCount().' 条  ',  

    'pages' => $paginationTop,  

    'itemCount'=>$totalItemFoundCount,  

    'prevPageLabel' => '上一页',  

    'cssFile'=>false,  

    'nextPageLabel' => '下一页',  

    'footer'=>'  ',  

));   

 

其中的 pagination 在 controller 中生成

[php] 

$paginationTop = new CPagination($totalItemFoundCount);  

$paginationTop->pageSize= $pageSize;  

 

然后把重写的 CLinkPager 放在  CGridView 前面即可。

运行后发现一个Bug ,就是 分页 不是 Ajax 的。

不是Ajax的不要紧, 关键是 分页和排序不能结合使用了。

原因很简单, 分页不是ajax 的,而排序是ajax 的, 两个 请求发出后 url 不在一个地方, 那么分页参数和 排序参数就 不再一地方, 当然无法结合使用。

解决方案: 统一起来。

要么统一为url排序&分页, 要么统一为ajax排序&分页。

url的简单, 设置 ajaxUpdate=>false,

ajax的也简单, 只要理解了本文第一部份说的 ajax 排序的原理,

之所以不能够 ajax 分页, 是因为我们的分页是 重写了, 而且还放在了CGridView 之外, 这样如何让 

jQuery('#keyword-grid').yiiGridView({'ajaxUpdate':['1','keyword-grid'],'ajaxVar':'ajax','pagerClass':'pager','loadingClass':'grid-view-loading','filterClass':'filters','tableClass':'items','selectableRows':1,'pageVar':'keyword_page'});

 

ajaxUpdate的时候 还去照顾到你写在外面的 CLinkPager 呢?

配置2个参数:

                    'ajaxUpdate'=>'datalist-grid, yw0',

                    'updateSelector'=>'.pager a, thead th a',

 

本来 ajaxUpdate 的作用范围 只是  datalist-gird , 现在我们告诉他 还要 作用在我们重写在grid 外面的 分页 ul  ,其id 是 yw0.

updateSelector 指定了 触发 ajaxUpdate 这个动作的html元素, 也是要保证 包含了 分页的链接和排序的链接 , 否则也是无法成功 ajax 排序/分页。

 

再看第2种重写方案:

 

上面第一种方案 太复杂了把, 既然问题的核心关键是 没有把自定义的 ClinkPager 放在 CGridView 中, 那我们就重写 CGridView将其放进去呗。

对,确实是可行的。

 

[php]  

Yii::import('zii.widgets.grid.CGridView');  

  

class EbuCGridView extends CGridView  

{  

    /**      

     * Renders the data items for the grid view. 

     */       

    public function renderItems()  

    {     

        if($this->dataProvider->getItemCount()>0 $this->showTableOnEmpty)  

        {     

            $this->renderCustomerPager();  

            echo "

itemsCssClass}\">\n";  

            $this->renderTableHeader();  

            ob_start();  

            $this->renderTableBody();  

            $body=ob_get_clean();  

            $this->renderTableFooter();  

            echo $body; // TFOOT must appear before TBODY according to the standard.  

            echo "

";  

            $this->renderCustomerPager();  

        }         

        else          

            $this->renderEmptyText();  

    }                     

  

    public $paginationTop;  

    public $totalItemCount;  

    public $totalItemFoundCount;  

    public function renderCustomerPager()  

    {                     

        $paginationTop = $this->paginationTop;  

        $totalItemCount = $this->totalItemCount;  

        $totalItemFoundCount = $this->totalItemFoundCount;  

        echo '

';  

        echo '

';  

        $this->widget('CLinkPager', array(  

            'header'=>'第 '.($paginationTop->getCurrentPage()*$paginationTop->getPageSize()+1).  

            ' - '.($paginationTop->getCurrentPage()*$paginationTop->getPageSize()+$paginationTop->getPageSize()).  

            ' 条, 共 '.$paginationTop->getItemCount().' 条  ',  

            'pages' => $paginationTop,  

            'itemCount'=>$totalItemFoundCount,  

            'prevPageLabel' => '上一页',  

            'cssFile'=>false,  

            'nextPageLabel' => '下一页',  

            'footer'=>'  ',  

        ));                       

....  

 

 

第3种方案:

 

前2种方案,说实话,都太麻烦了,破坏了yii 自身的机制, 又在其上弥补了半天。。

 

最好的方案 ,还是 配置 CGridView 的 'pager' ,来实现我们要更复杂的CLinkPager的目标。

 

但是,有些时候还真必须用第 1、2种方案;

比如我应用的情况是:

用 Coreseek 全文索引 查询出 数据 的id ,再 用 id 来到数据库中找出数据,形成 CActiveDataProvider ,最后用 CGridView来展示。

 

我这里的 CDbCriteria 如下

[php]  

$criteria = new CDbCriteria;  

$criteria->join  = 'LEFT JOIN site2 AS si** ON t.**=**.domain_hash';  

$criteria->addInCondition('t.id', $IDARRAY);  

$criteria->select = array("t.id", "t.content", "t.pubtime", "t.url", "t.reply_num", "t.retweet_num", "site_config.site_name");  

$criteria->order = 'FIND_IN_SET(t.id, "'.join(",", $IDARRAY).'")';  

 

其中 变量 IDARRAY 正是 coreseek 得到的 一个 id 组成的数组

如果按照 普通的

 

[php]  

$dataProvider = new CActiveDataProvider('TData', array(  

    'criteria'=>$criteria,  

    'pagination'=>array(  

        'pageSize'=>10,  

    ),     

));    

 

是不满足我的需求的。

因为我的分页和排序都是在 coreseek 中完成的, 这里用 CActiveDataProvider 只是提供了当前页(比如每一页10条记录)的10条记录。

 

end。

有更好的建议和意见,欢迎提出共同学习。



성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.