刷新网格时,ExtJs 4.2错误'getById调用了本地缓存中不存在的ID'

时间:2013-11-13 12:09:02

标签: javascript rest extjs extjs4.2

以下是我所拥有的: enter image description here

单击其中一个框时,下面的列表将在服务器端进行过滤。

如果我选择网格中的行然后提交过滤器,我会收到以下错误:

“getById调用了本地缓存中不存在的ID”

enter image description here

即使过滤器确实包含我选择的记录,也会引发此问题。

这是模块:

Ext.define('NG.model.auxClasses.notifications.WhatsNew', {
    extend: 'Ext.data.Model',
    idProperty: 'iD',
    autoLoad: true,
    fields: [
        { name: 'iD', type: 'int' },
        { name: 'isActive', type: 'boolean' },
        { name: 'documentIdentifier', type: 'string' },
        { name: 'sourceSiteName', type: 'string' },
        { name: 'targetSiteName', type: 'string' },
        { name: 'createDate', type: 'date', dateFormat: 'c' },
        { name: 'businessArchiveEvent', type: 'string' },
        { name: 'businessArchive', type: 'string' },
        { name: 'previousWhatsNewEvents' },
        { name: 'isPin', type: 'boolean' },
        { name: 'IsDocumentReadByMe', type: 'boolean' },
        { name: 'isDocumentReadByOthers', type: 'boolean' },
        { name: 'documentYear', type: 'int' },
        { name: 'businessDirection', type:'int'}
    ],

    // self association model
    associations: [{
        type: 'hasMany',
        model: 'auxClasses.notifications.WhatsNew',
        name: 'previousWhatsNewEvents',
        primaryKey: 'id',
        associationKey: 'previousWhatsNewEvents'
    }],

    proxy: {
        type: 'rest',
        url: 'api/WhatsNew/'
    }

});

这是商店:

Ext.define('NG.store.WhatsNews', {
    extend: 'NG.store.AbstractStore',
    model: 'NG.model.auxClasses.notifications.WhatsNew',
    alias: 'store.whatsnewstore',
    autoLoad:true,
    buffered: true,
    pageSize: 50
});

更新

我跟着兔子走到了洞口,找到了一个我不确定会起作用的解决方法:

这是我失败的地方:

refresh: function() {
        ...

        // Don't need to do this on the first refresh
        if (me.hasFirstRefresh) {
        // Some subclasses do not need to do this. TableView does not need to do this.                   
               if (me.refreshSelmodelOnRefresh !== false) {
                    me.selModel.refresh();
                } else {
                    // However, even if that is not needed, pruning if pruneRemoved is true (the default) still needs doing.
                    me.selModel.pruneIf(); <<< HERE WE FAIL. THIS METHODS CALLS THE GET BY ID
                }
            }

           ...
    }

所以在我看来,我添加了以下视图配置:

viewConfig: {
        refreshSelmodelOnRefresh:true // Workaround : if this is not set to true when the grid will refresh and a record will be selected we will get an ext error 
    },

这解决了引发的错误,但我不确定最终结果以及它可能会在以后造成的伤害。

如果有人可以遮挡一些光......

是否有解决方法?

5 个答案:

答案 0 :(得分:1)

你可以做一些事情 -

  1. 将pageSize增加到至少100,缓冲商店并非真正设计用于小型记录集

  2. 使用以下覆盖:

  3. 当存储是缓冲类型时,此覆盖修复了多个错误并修复了导致初始hasId无法工作的错误,因为store.getById()方法需要ID而不是记录,同时也强制进行双重验证找不到,因为它将两个检查都放在一个if语句中。

    @src:http://www.sencha.com/forum/showthread.php?258397-4.2.0-RC-Selecting-a-grid-s-row-with-a-buffered-store-causes-a-JavaScript-error/page2

     Ext.override(Ext.selection.Model, {
      storeHasSelected: function(record) {
        var store = this.store,
            records,
            len, id, i, m;
    
        if (record.hasId()) {
            return store.getById(record.getId());
        } else {
            if (store.buffered) {//on buffered stores the map holds the data items
                records = [];
                for (m in store.data.map) {
                    records = records.concat(store.data.map[m].value);
                }
            } else {
                records = store.data.items;
            }
            len = records.length;
            id = record.internalId;
    
    
            for (i = 0; i < len; ++i) {
                if (id === records[i].internalId) {
                    return true;
                }
            }
        }
        return false;
      }
    });
    

    如果1和2都不起作用,请尝试:

    Ext.view.AbstractView.override({
        refresh: function() {
            var me = this,
                targetEl,
                targetParent,
                oldDisplay,
                nextSibling,
                dom,
                records;
    
            if (!me.rendered || me.isDestroyed) {
                return;
            }
    
            if (!me.hasListeners.beforerefresh || me.fireEvent('beforerefresh', me) !== false) {
                targetEl = me.getTargetEl();
                records = me.getViewRange();
                dom = targetEl.dom;
    
                // Updating is much quicker if done when the targetEl is detached from the document, and not displayed.
                // But this resets the scroll position, so when preserving scroll position, this cannot be done.
                if (!me.preserveScrollOnRefresh) {
                    targetParent = dom.parentNode;
                    oldDisplay = dom.style.display;
                    dom.style.display = 'none';
                    nextSibling = dom.nextSibling;
                    targetParent.removeChild(dom);
                }
    
                if (me.refreshCounter) {
                    me.clearViewEl();
                } else {
                    me.fixedNodes = targetEl.dom.childNodes.length;
                    me.refreshCounter = 1;
                }
    
                // Always attempt to create the required markup after the fixedNodes.
                // Usually, for an empty record set, this would be blank, but when the Template
                // Creates markup outside of the record loop, this must still be honoured even if there are no
                // records.
                me.tpl.append(targetEl, me.collectData(records, me.all.startIndex));
    
                // The emptyText is now appended to the View's element
                // after any fixedNodes.
    
    
                if (typeof records !== 'undefined' && records !== undefined && records && records.length < 1) { 
                    // Process empty text unless the store is being cleared.
                    if (!this.store.loading && (!me.deferEmptyText || me.hasFirstRefresh)) {
                        Ext.core.DomHelper.insertHtml('beforeEnd', targetEl.dom, me.emptyText);
                    }
                    me.all.clear();
                } else {
                    me.collectNodes(targetEl.dom);
                    me.updateIndexes(0);
                }
    
                // Don't need to do this on the first refresh
                if (me.hasFirstRefresh) {
                    // Some subclasses do not need to do this. TableView does not need to do this.
                    if (me.refreshSelmodelOnRefresh !== false) {
                        me.selModel.refresh();
                    } else {
                        // However, even if that is not needed, pruning if pruneRemoved is true (the default) still needs doing.
                        me.selModel.pruneIf();
                    }
                }
    
                me.hasFirstRefresh = true;
    
                if (!me.preserveScrollOnRefresh) {
                    targetParent.insertBefore(dom, nextSibling);
                    dom.style.display = oldDisplay;
                }
    
                // Ensure layout system knows about new content size
                this.refreshSize();
    
                me.fireEvent('refresh', me);
    
                // Upon first refresh, fire the viewready event.
                // Reconfiguring the grid "renews" this event.
                if (!me.viewReady) {
                    // Fire an event when deferred content becomes available.
                    // This supports grid Panel's deferRowRender capability
                    me.viewReady = true;
                    me.fireEvent('viewready', me);
                }
            }
        }
    });
    

答案 1 :(得分:1)

在我的代码中,我使用带有网格的缓冲区存储,然后我收到此错误。

我用这个解决了它

selModel: {
    pruneRemoved: false
}

答案 2 :(得分:0)

请尝试此覆盖

    Ext.data.Store.override({
        getById: function(id) {
            var result = (this.snapshot || this.data).findBy(function(record) {
                return record.getId() === id;
            });
            if (this.buffered && !result) {
                return [];
            }
            return result;
        }
    });

答案 3 :(得分:0)

对于ExtJS 5,覆盖BufferedStore而不是Store:

Ext.data.BufferedStore.override({
    getById: function(id) {
        var result = (this.snapshot || this.data).findBy(function(record) {
            return record.getId() === id;
        });
        if (this.buffered && !result) {
            return [];
        }
        return result;
    }
});

答案 4 :(得分:0)

您不需要使用上述任何替代。如果在使用缓冲存储时出现此错误,只需设置此处指定的pruneRemoved:false属性: http://docs.sencha.com/extjs/4.2.3/#!/api/Ext.selection.Model-cfg-pruneRemoved

e.g。

selModel: Ext.create('Ext.selection.RowModel', {
                pruneRemoved: false
})