关于删除Ext分页表格最后一页全部数据后页面无效的问题

关键词

Ext,Ext.toolbar.paging

 

环境说明

开发环境:Eclipse Indigo


浏览器环境:Chrome


问题描述

在使用表格展示大量数据时,由于页面性能受限,通常使用分页功能逐页展示数据。

Ext中,Ext.toolbar.paging组件实现表格数据的分页显示,但是在测试过程中发现,若将最后一页的全部数据一次性删除,表格页面将没有任何数据显示(而此时后台实际是有数据的)。如下图:


初始首页,可以看到总共有3590条数据,共36个分页


删除最后一页后的问题页面,页面跳转按钮灰化,总页数、当前页数、记录条数等信息均显示为0


问题详述

定义用户的store如下,设定每页展示100条数据,使用proxy从后台servlet获取json格式的返回数据,返回的人员信息存放在”personArray”,返回的总记录条数存放在”totalCount”。

Ext.create('ExamPlatform.datamodel.PeopleM'); // 必须要先创建一次,否则store无法找到对应的model 
    var personInfoStore = Ext.create('Ext.data.Store', {
        pageSize: 100,
        autoDestroy: true,
        model: 'ExamPlatform.datamodel.PeopleM',
        proxy: {
            type: 'ajax',
            url: '/senhwa/queryPersonInfoServlet',
            reader: {
                type: 'json',
                root: 'personArray', // 存放当前返回的数据
                totalProperty  : 'totalCount'  //存放总共的记录数
            }
        }

Servlet中根据前台传送的参数 start和limit来返回对应的数据信息。这两个参数由Ext自动封装,start即起始记录的序号,limit即在store中定义的pageSize。

//获取limit和start参数
    Integer limit = 50;
    Integer start = 0;
    try
    {
        limit = Integer.valueOf(request.getParameter("limit"));
        start = Integer.valueOf(request.getParameter("start"));
    } catch (NumberFormatException e1)
    {
        e1.printStackTrace();
}

try
    {
        PrintWriter out = response.getWriter();
        List<PersonBean> personBeanList = PersonDAO.queryPersons();
        int totalCount = personBeanList.size();
        //判断末尾记录的序号
        int end = CommonUtil.floor((start + limit), totalCount);
        JSONArray array = JSONArray.fromObject(personBeanList.subList(start, end));
        String jsonArray = array.toString();
        String retJson = "{\"totalCount\":\"" + totalCount + "\",\"personArray\":" + jsonArray + "}"; 
        out.write(retJson);
        out.close();
    } 
    catch (PersonDbException e)
    {
        e.printStackTrace();
    } 
    catch (IOException e)
    {
        e.printStackTrace();
    }

这里插一句,通过测试可以发现,Ext.toolbar.paging组件初始传给后台的[start,limit]为[0,100],点击next后传给后台[100,100],以此类推。由于总记录数不一定等于总页数×每页展示记录条数,所以在截取列表数据前,需要先比较start+limit与totalCount的大小,取其小者。

 

下面两张图分别是初始的第一页和第二页的数据,注意总页数是36页,总记录条数是3590条,当前第101条数据为“韩波”。



回到首页,将首页的100条数据全部选中并删除


可以看到序号1的记录正式原序号101的韩波,此时总记录条数变更为3490,总页数变更为35页,但是当前页号依然为1。


删除数据后,personInfoStore再次load数据

PersonInfoDwr.removePersonById(jsonStr, function()
	{
	    //刷新列表
	    personInfoStore.load();
	});

由此可以推测,传递给后台的[start,limit]依然是[0,100],即当前页号不变(依然为1),起始记录序号不变(依然为0)

首先需要说明的是,针对一个列表中的数据进行删除,后面的数据自动补位,这样的处理符合习惯的。

 

让我们先查看一下最后一页(35)和最后第二页(34)的数据。



想象一下,当把最后一页的数据全部删除后,页面会展示什么数据?

·是否会像删除首页一样展示后续的数据?不可能了,因为后面已经没有数据了。

·不展示任何数据?可以理解。

·展示前一页的数据?这个是最符合习惯的,删除了最后一页,原来的最后第二页就应该展示到最后一页的地方。

那么我们来删除最后一页数据,看看会是什么效果。



如图所示,删除后没有数据显示,且当前页总页数均显示为0,总记录数为0。页面跳转按钮灰化不可用。

通俗点说,这个页面不可用了!

 

为什么会出现这种情况?

首先,我们来查看之前操作传递给后台的数据如下:

 

[start,limit,total]

进入首页

[0,100,3590]

删除首页全部数据

[0,100,3490]

进入最后一页

[3400,100,3490]

删除最后一页全部数据

[3400,100,3400]

注意最后一行的start和total是相等的,即此时,截取到的列表将是空的。这也就是为什么删除后页面会没有数据展示。

但是为什么页面按钮会灰化呢?

查看Ext.toolbar.paging的源码可以看到,当页面发现数据为空时,将这些按钮设置不可用了。

count = me.store.getCount();
        isEmpty = count === 0;
        if (!isEmpty) {
            pageData = me.getPageData();
            currPage = pageData.currentPage;
            pageCount = pageData.pageCount;
            afterText = Ext.String.format(me.afterPageText, isNaN(pageCount) ? 1 : pageCount);
        } else {
            currPage = 0;
            pageCount = 0;
            afterText = Ext.String.format(me.afterPageText, 0);
        }

        Ext.suspendLayouts();
        me.child('#afterTextItem').setText(afterText);
        me.child('#inputItem').setDisabled(isEmpty).setValue(currPage);
        me.child('#first').setDisabled(currPage === 1 || isEmpty); //为空则不可用
        me.child('#prev').setDisabled(currPage === 1  || isEmpty); //为空则不可用
        me.child('#next').setDisabled(currPage === pageCount  || isEmpty); //为空则不可用
        me.child('#last').setDisabled(currPage === pageCount  || isEmpty); //为空则不可用
        me.child('#refresh').enable();
        me.updateInfo();
        Ext.resumeLayouts(true);

这种处理其实是正确的,即初始表格为空时,不能使用这些按钮。

但是在这里,这样的处理就显然不妥了,因为页面直接不可用了,即使刷新页面也无济于事。

问题其实还是出在删除最后一页全部数据后,传递给后台的[3400,100,3400],倘若此时可以传递给后台[3300,100,3400],则可以解决当前的问题。

是否可以在sevlet中优化算法,当发现截取到的列表将为空时,自动返回最后一个limit长度的数据?结论是不可以!因为以上面的例子来说,删除第35页的数据后,sevlet会返回第34页的数据给页面,但是页面不知道后台返回给它的是第34页的数据,所以页面的编号依然是从3401开始,实际应该是3301开始。即序号和数据会不对应。

由于[start,limit]是Ext框架封装传递的,我们无法在页面去修改。

而经过走读paging.js发现,store有一个currentPage的属性,所以最后采用的方法就是在删除数据前,判断满足条件的时候,主动向前翻一页。

//--------------------修正currentPage数值-----------------------------------------------            
            //•这里的处理目的在于解决将最后一页全删除后,Ext默认的当前页(currentPage)值不变化,造成加载到store中的数据为空
            //•当删除的数据不是最后一页时,currentPage不需要变化,可以直接加载到后面的数据,store不为空
            //•但是当删除最后一页的数据时,若currentPage不变化,由于后面没有数据,会造成store为空,
            //在Paging.js中会将当前页,总页等一起设置为0,造成表格不可用
            //•当删除的即是最后一页,也是第一页时(即所有数据都展示在一页上)时,也不需要处理。
            var totalCount = personInfoStore.getTotalCount(); // 所有的记录数,不单单是当前页展示的数据
            var pageSize = personInfoStore.pageSize; // 一页上面展示的记录条数
            var curPage = personInfoStore.currentPage; // 当前页码
            var fromRecord = ((curPage - 1) * pageSize) + 1; // 当前页展示的起始记录号
            var toRecord = Math.min(curPage * pageSize, totalCount); // 当前页展示的结尾记录号
            var totalOnCurPage = toRecord - fromRecord + 1; // 当前页展示的记录条数
            var totalPageCount = Math.ceil(totalCount / pageSize); // 总的页数
            var delCount = length; // 删除的记录条数
            //若当前页是最后一页,且不是仅有的一页,且删除的记录数是当前页上的所有记录数
            if (curPage === totalPageCount && totalPageCount != 1 && delCount === totalOnCurPage)
            {
                personInfoStore.currentPage--;
            }
//----------------------------------------------------------------------------------------------------          
再次进行验证,删除第34页后,正确展示第33页的内容



后记

这样修改后,这个表格的功能就比较完善了,但是从实现上来看,下一个表格依然会有这样的问题,最好的办法当然是修改paging.js的源码,但同时也会造成后续更换新版本Ext的兼容问题,各有利弊吧。



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值