ExtJs4.2示例中infinite-scroll出现PageMap asked for range which it does not have错误及解决

ExtJS的表格做的非常强大,但是ExtJS的源码相当庞大当框架内部出现问题的时候非常难查找到解决办法。最近因为学习的需要,我们在使用ExtJSP制作公司内部的管理系统,但是在使用ExtJS自带的examples中的gird中的infinite-scroll时,却出现了“Ext.data.PageMap.getRange(): PageMap asked for range which it does not have”的错误,最终只有通过重载它自身的方法才解决问题。

环境描述:ext-4.2.1.883,谷歌浏览器调试工具(火狐浏览器需要使用fireBug)

错误描述:由于引用ExtJSP不同的包会出现不同的提示这里就以ext-all-dev.js和ext-dev.js两种不同的引用方式来说明。

当引用ext-all-dev.js时错误如下图描述:


当引用ext-dev.js时错误如下图描述:


两种引用方式都在说明一个问题:[E] Ext.data.PageMap.getRange(): PageMap asked forrange which it does not have。

解决办法:通过debug Ext的代码最终查找到 ext-4.2.1.883/src/view/Table.js 中的方法“renderRow”出错(这是引用完整ExtJS代码ext-dev.js时的情况,如果引用了ext-all-dev.js,那么“renderRow”在150317行),这是类'Ext.view.Table'中的一个方法。

通过重载Ext.view.Table中的方法解决问题,代码如下:

Ext.override(Ext.view.Table, {
	renderRow: function(record, rowIdx, out) {
        var me = this,
            isMetadataRecord = rowIdx === -1,
            selModel = me.selModel,
            rowValues = me.rowValues,
            itemClasses = rowValues.itemClasses,
            rowClasses = rowValues.rowClasses,
            cls,
            rowTpl = me.rowTpl;

        // Set up mandatory properties on rowValues
        rowValues.record = record;
        rowValues.recordId = record.internalId;
        rowValues.recordIndex = rowIdx;
        rowValues.rowId = me.getRowId(record);
        rowValues.itemCls = rowValues.rowCls = '';
        if (!rowValues.columns) {
            rowValues.columns = me.ownerCt.columnManager.getColumns();
        }

        itemClasses.length = rowClasses.length = 0;

        // If it's a metadata record such as a summary record.
        // So do not decorate it with the regular CSS.
        // The Feature which renders it must know how to decorate it.
        if (!isMetadataRecord) {
            itemClasses[0] = Ext.baseCSSPrefix + "grid-row";
            if (selModel && selModel.isRowSelected) {
            	//正是这里出错,原来的方法是
            	//selModel.isRowSelected(rowIdx + 1)
            	//从而导致PageMap的越界错误
                if (selModel.isRowSelected(rowIdx)) {
                    itemClasses.push(me.beforeSelectedItemCls);
                }
                if (selModel.isRowSelected(record)) {
                    itemClasses.push(me.selectedItemCls);
                }
            }

            if (me.stripeRows && rowIdx % 2 !== 0) {
                rowClasses.push(me.altRowCls);
            }

            if (me.getRowClass) {
                cls = me.getRowClass(record, rowIdx, null, me.dataSource);
                if (cls) {
                    rowClasses.push(cls);
                }
            }
        }
        
        if (out) {
            rowTpl.applyOut(rowValues, out);
        } else {
            return rowTpl.apply(rowValues);
        }
    }
});

在重载这个方法之后,可能会影响其它的grid,但是在目前的使用中其它grid正常运行,没有出现任何问题!

其它问题:关于这个问题有许多人都在这个版本中遇到,但是据说在5.0之后的收费版中已经不存在了。

可以参考以下两篇文章的描述:

https://www.sencha.com/forum/showthread.php?264733-Grid-with-Infinite-Scroling-in-4.2.1-Reload-Function&p=979464&viewfull=1

http://www.4byte.cn/question/601040/get-rid-of-pagemap-asked-for-range-which-it-does-not-have-exception.html

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

测试代码(Java)

index.jsp:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Welcome</title>
    <link rel="stylesheet" type="text/css" href="ext42/resources/css/ext-all.css" />
    <script type="text/javascript" src="ext42/ext-all-dev.js"></script>
    <script type="text/javascript" src="ext42/locale/ext-lang-zh_CN.js"></script>
    <script type="text/javascript" charset="UTF-8" src="js/test.js"></script>
  </head>
  <body>
  </body>
</html>

test.js(也就是把ext-4.2.1.883/examples/grid/infinite-scroll.js做了简化):

Ext.require([
    'Ext.grid.*',
    'Ext.data.*',
    'Ext.util.*',
    'Ext.grid.plugin.BufferedRenderer'
]);

Ext.onReady(function(){
    Ext.override(Ext.view.Table, {
        renderRow: function(record, rowIdx, out) {
            var me = this,
                isMetadataRecord = rowIdx === -1,
                selModel = me.selModel,
                rowValues = me.rowValues,
                itemClasses = rowValues.itemClasses,
                rowClasses = rowValues.rowClasses,
                cls,
                rowTpl = me.rowTpl;
    
            // Set up mandatory properties on rowValues
            rowValues.record = record;
            rowValues.recordId = record.internalId;
            rowValues.recordIndex = rowIdx;
            rowValues.rowId = me.getRowId(record);
            rowValues.itemCls = rowValues.rowCls = '';
            if (!rowValues.columns) {
                rowValues.columns = me.ownerCt.columnManager.getColumns();
            }
    
            itemClasses.length = rowClasses.length = 0;
    
            // If it's a metadata record such as a summary record.
            // So do not decorate it with the regular CSS.
            // The Feature which renders it must know how to decorate it.
            if (!isMetadataRecord) {
                itemClasses[0] = Ext.baseCSSPrefix + "grid-row";
                if (selModel && selModel.isRowSelected) {
                    //正是这里出错,原来的方法是
                    //selModel.isRowSelected(rowIdx + 1)
                    //从而导致PageMap的越界错误
                    if (selModel.isRowSelected(rowIdx)) {
                        itemClasses.push(me.beforeSelectedItemCls);
                    }
                    if (selModel.isRowSelected(record)) {
                        itemClasses.push(me.selectedItemCls);
                    }
                }
    
                if (me.stripeRows && rowIdx % 2 !== 0) {
                    rowClasses.push(me.altRowCls);
                }
    
                if (me.getRowClass) {
                    cls = me.getRowClass(record, rowIdx, null, me.dataSource);
                    if (cls) {
                        rowClasses.push(cls);
                    }
                }
            }
            
            if (out) {
                rowTpl.applyOut(rowValues, out);
            } else {
                return rowTpl.apply(rowValues);
            }
        }
    });
    
    Ext.define('ForumThread', {
        extend: 'Ext.data.Model',
        fields: ['key', 'value'],
        idProperty: 'key'
    });

    // create the Data Store
    var store = Ext.create('Ext.data.Store', {
        id: 'store',
        model: 'ForumThread',
        remoteGroup: true,
        // allow the grid to interact with the paging scroller by buffering
        buffered: true,
        leadingBufferZone: 0,
        pageSize: 100,
        proxy: {
            // load using script tags for cross domain, if the data in on the same domain as
            // this page, an Ajax proxy would be better
            type: 'ajax',
            url: 'DataServer',
            reader: {
                root: 'data',
                totalProperty: 'totalCount'
            },
            // sends single sort as multi parameter
            simpleSortMode: true,
            // sends single group as multi parameter
            simpleGroupMode: true,

            // This particular service cannot sort on more than one field, so grouping === sorting.
            groupParam: 'sort',
            groupDirectionParam: 'dir'
        },
        sorters: [{
            property: 'key',
            direction: 'ASC'
        }],
        autoLoad: true,
        listeners: {

            // This particular service cannot sort on more than one field, so if grouped, disable sorting
            groupchange: function(store, groupers) {
                var sortable = !store.isGrouped(),
                    headers = grid.headerCt.getVisibleGridColumns(),
                    i, len = headers.length;
                
                for (i = 0; i < len; i++) {
                    headers[i].sortable = (headers[i].sortable !== undefined) ? headers[i].sortable : sortable;
                }
            },

            // This particular service cannot sort on more than one field, so if grouped, disable sorting
            beforeprefetch: function(store, operation) {
                if (operation.groupers && operation.groupers.length) {
                    delete operation.sorters;
                }
            }
        }
    });

    var grid = Ext.create('Ext.grid.Panel', {
        width: 700,
        height: 500,
        collapsible: true,
        title: 'ExtJS.com - Browse Forums',
        store: store,
        loadMask: true,
        selModel: {
            pruneRemoved: false
        },
        multiSelect: true,
        viewConfig: {
            trackOver: false
        },
        features:[{
            ftype: 'grouping',
            hideGroupedHeader: false
        }],
        // grid columns
        columns:[{
            xtype: 'rownumberer',
            width: 100,
            sortable: false
        },{
            text: "key",
            dataIndex: 'key',
            width: 100,
            sortable: true
        },{
            text: "value",
            dataIndex: 'value',
            align: 'center',
            flex: 1,
            sortable: false
        }],
        renderTo: Ext.getBody()
    });
});

DataServer.java(服务器端servlet代码):

package com.ext.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DataServer extends HttpServlet {

	/**
	 * Constructor of the object.
	 */
	public DataServer() {
		super();
	}

	/**
	 * Destruction of the servlet. <br>
	 */
	public void destroy() {
		super.destroy(); // Just puts "destroy" string in log
		// Put your code here
	}

	/**
	 * The doGet method of the servlet. <br>
	 *
	 * This method is called when a form has its tag value method equals to get.
	 * 
	 * @param request the request send by the client to the server
	 * @param response the response send by the server to the client
	 * @throws ServletException if an error occurred
	 * @throws IOException if an error occurred
	 */
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		
		PrintWriter out = response.getWriter();

		String pageStr = request.getParameter("page");
		String startStr = request.getParameter("start");
		String limitStr = request.getParameter("limit");
		
		pageStr = pageStr==null || pageStr.equals("") ? "0":pageStr;
		startStr = startStr==null || startStr.equals("") ? "0":startStr;
		limitStr = limitStr==null || limitStr.equals("") ? "100":limitStr;
		
		int page = Integer.valueOf(pageStr);
		int start = Integer.valueOf(startStr);
		int limit = Integer.valueOf(limitStr);
		
		int count = 600;
		
		StringBuffer buffer = new StringBuffer();
		buffer.append("{'totalCount':'"+count+"','data':[");
		for (int i=start; i< start+limit; i++){
			buffer.append("{'key':'key-"+i+"','value':'val-"+i+"'},");
		}
		buffer.delete(buffer.lastIndexOf(","), buffer.length());
		buffer.append("]}");
		out.write(buffer.toString());
		//out.write("<html>sadf</html>");
		out.flush();
		out.close();
	}

	/**
	 * The doPost method of the servlet. <br>
	 *
	 * This method is called when a form has its tag value method equals to post.
	 * 
	 * @param request the request send by the client to the server
	 * @param response the response send by the server to the client
	 * @throws ServletException if an error occurred
	 * @throws IOException if an error occurred
	 */
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doGet(request, response);
	}

	/**
	 * Initialization of the servlet. <br>
	 *
	 * @throws ServletException if an error occurs
	 */
	public void init() throws ServletException {
		// Put your code here
	}

}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值