Occassionally I get the exception "PageMap asked for range which it does not have" from my Ext Js 4.2.1 infinite scrolling grid. It is raised in data/PageMap.js on line 211. Of course one should not ask for non-existing entries, but this is sometimes done by the framework itself. Seems to be somehow connected to adding/removing records or reloading the grid. There are already some threads on this topic in the Sencha forum, e.g. this, but no killer solution or bugfix was proposed yet.
Meanwhile, I have to keep this exception from the users' eyes. What would be a good way to do so? Tricky thing is that it is sometimes provoked just by the user moving the scrollbar, so there is no single line of my code directly involved.
Occassionally I get the exception "PageMap asked for range which it does not have" from my Ext Js 4.2.1 infinite scrolling grid. It is raised in data/PageMap.js on line 211. Of course one should not ask for non-existing entries, but this is sometimes done by the framework itself. Seems to be somehow connected to adding/removing records or reloading the grid. There are already some threads on this topic in the Sencha forum, e.g. this, but no killer solution or bugfix was proposed yet.
Meanwhile, I have to keep this exception from the users' eyes. What would be a good way to do so? Tricky thing is that it is sometimes provoked just by the user moving the scrollbar, so there is no single line of my code directly involved.
Share Improve this question edited Jul 17, 2013 at 11:19 Christoph asked Jul 17, 2013 at 6:39 ChristophChristoph 1,02311 silver badges24 bronze badges4 Answers
Reset to default 4I found the root cause to be that when it's rendering rows, it determines if it's before a selected row. If it's working on the last row, it still looks for row + 1. (Ext.view.Table:931 in 4.2.1)
My simple solution is to just make it return false:
Ext.override(Ext.selection.RowModel,
{
isRowSelected: function (record, index)
{
try
{
return this.isSelected(record);
}
catch (e)
{
return false;
}
}
});
Christoph,
I have similar troubles with "PageMap asked for range which it does not have" during asynchronuous refreshing of grids. I catched some of sources of errors in the ExtJS 4.2.1 code and created simple override, that works for me. You can try if it will work for you. I will be happy for your feedback.
Ext.override(Ext.view.Table, {
getRecord: function (node) {
node = this.getNode(node);
if (node) {
var recordIndex = node.getAttribute('data-recordIndex');
if (recordIndex) {
recordIndex = parseInt(recordIndex, 10);
if (recordIndex > -1) {
// Eliminates one of sources of "PageMap asked for range which it does not have" error
if (this.store.getCount() > 0) {
return this.store.data.getAt(recordIndex);
}
}
}
return this.dataSource.data.get(node.getAttribute('data-recordId'));
}
},
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;
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 (!isMetadataRecord) {
itemClasses[0] = Ext.baseCSSPrefix + "grid-row";
if (selModel && selModel.isRowSelected) {
var storeRows = this.getStore().getCount();
// Eliminates one of sources of "PageMap asked for range which it does not have" error
if (rowIdx + 1 < storeRows) {
if (selModel.isRowSelected(rowIdx + 1)) {
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);
}
}
});
all these codes don't work for me, after many debugging I wrote this override which solve the problem.
Ext.define('overrides.LruCache', {
override: 'Ext.util.LruCache',
// private. Only used by internal methods.
unlinkEntry: function (entry) {
// Stitch the list back up.
if (entry) {
if (this.last && this.last.key == entry.key)
this.last = entry.prev;
if (this.first && this.first.key == entry.key)
this.first = entry.next;
if (entry.next) {
entry.next.prev = entry.prev;
} else {
this.last = entry.prev;
}
if (entry.prev) {
entry.prev.next = entry.next;
} else {
this.first = entry.next;
}
entry.prev = entry.next = null;
}
}
});
This is my solution for my specific case with the same error
it somehow lost DOM element for child this code fix that
Ext.define('override.Ext.view.Table', {
/**
* Returns the node given the passed Record, or index or node.
* @param {HTMLElement/String/Number/Ext.data.Model} nodeInfo The node or record
* @param {Boolean} [dataRow] `true` to return the data row (not the top level row if wrapped), `false`
* to return the top level row.
* @return {HTMLElement} The node or null if it wasn't found
*/
override: 'Ext.view.Table',
getNode: function (nodeInfo, dataRow) {
// if (!dataRow) dataRow = false
var fly,
result = this.callParent(arguments)
if (result && result.tagName) {
if (dataRow) {
if (!(fly = Ext.fly(result)).is(this.dataRowSelector)) {
result = fly.down(this.dataRowSelector, true)
}
} else if (dataRow === false) {
if (!(fly = Ext.fly(result)).is(this.itemSelector)) {
result = fly.up(this.itemSelector, null, true)
}
if (this.xtype == 'gridview' && !this.body.dom.querySelector(`#${result.id}`)) {
result = null
}
}
}
return result
},
})