• yii_CGridView_ajax_pagination_and_ajax_sort


    本文主要内容:

    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} <div class="page_area">{pager} {summary}</div>',
        'pager'=>array('cssFile'=>false),
        'ajaxUpdate'=>true,
        'columns'=>array(
            array(
                'name'=>'leader_name',
                'value'=>'$data->event',
                'header'=>'关键词名称',
                'headerHtmlOptions'=>array('width'=>'130px'),
            ), .... ....

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


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


    <script type="text/javascript" src="/chuanmei/assets/f5d36ac5/jquery.ba-bbq.js"></script>
    <script type="text/javascript" src="/chuanmei/assets/fb90bba/gridview/jquery.yiigridview.js"></script>
    <script type="text/javascript">
    /*<![CDATA[*/
    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'});
    });
    /*]]>*/
    </script>


    其中会发现 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 条  



    /***

    author: php攻城师

    http://blog.csdn.net/phpgcs

    ***/

    先看第1种重写方案:


    重写 CLinkpager 如下:

            $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 中生成

            $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 "<table class="{$this->itemsCssClass}">
    ";
                $this->renderTableHeader();
                ob_start();
                $this->renderTableBody();
                $body=ob_get_clean();
                $this->renderTableFooter();
                echo $body; // TFOOT must appear before TBODY according to the standard.
                echo "</table>";
                $this->renderCustomerPager();
            }       
            else        
                $this->renderEmptyText();
        }                   
    
        public $paginationTop;
        public $totalItemCount;
        public $totalItemFoundCount;
        public function renderCustomerPager()
        {                   
            $paginationTop = $this->paginationTop;
            $totalItemCount = $this->totalItemCount;
            $totalItemFoundCount = $this->totalItemFoundCount;
            echo '<div class="page_area" style="text-align:right;">';
            echo '<div class="pager">';
            $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 如下

            $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 组成的数组

    如果按照 普通的


            $dataProvider = new CActiveDataProvider('TData', array(
                'criteria'=>$criteria,
                'pagination'=>array(
                    'pageSize'=>10,
                ),   
            ));  


    是不满足我的需求的。

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


    end。

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



  • 相关阅读:
    用面向对象的方法重写选项卡
    js 深入理解原型模式
    ECMAScript中的两种属性
    引用类型
    js 变量、作用域和内存问题
    html5 canvas画布尺寸与显示尺寸
    网页画板制作
    了解数组中的队列方法,DOM中节点的一些操作
    JavaScript中的数组对象遍历、读写、排序等操作
    this在方法赋值过程中无法保持(隐式丢失)
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3327378.html
Copyright © 2020-2023  润新知