列表的 PullRefresh 插件不处理 ChainedStore 的可能性

PullRefresh plugin of a List doesn't handle ChainedStore possibility

使用 Ext JS 7.1 Modern,我准备了一个例子来说明问题。

当我的主存储上有远程过滤器时,将 dataview.List 绑定到 ChainedStore 可以正确处理我的本地过滤。但是,当我还向列表中添加 PullRefresh 插件时,在拉动刷新期间出现错误。我从源代码中看到插件没有考虑列表存储可以是 ChainedStore.

的可能性

我已经尝试用 Sencha Fiddle 来解释问题,并附上了下面的代码。

我通过重写 Ext.dataview.pullrefresh.PullRefresh 插件的 fetchLatestonLatestFetched 方法暂时解决了这个问题,如果列表的存储是 ChainedStore。但我认为必须更新源代码才能处理这种情况。

app.js

Ext.define('App.model.Test', {
    extend: 'Ext.data.Model',

    fields: ['id', 'firstName', 'lastName']
});

Ext.define('App.store.Test', {
    extend: 'Ext.data.Store',
    alias: 'store.teststore',

    model: 'App.model.Test'
});

Ext.define('App.viewmodel.Test', {
    extend: 'Ext.app.ViewModel',
    alias: 'viewmodel.test',
    data: {
        query: ''
    },
    stores: {
        test: {
            type: 'teststore',
            autoLoad: true,
            proxy: {
                type: 'ajax',
                url: 'names.json',
                reader: {
                    type: 'json',
                    rootProperty: 'data'
                }
            },

            remoteFilter: true,
            filters: {
                property: 'id',
                value: 1
            }
        },
        chained: {
            type: 'chained',

            autoLoad: true,
            source: '{test}'
        }
    }
});

Ext.define('App.controller.TestController', {
    extend: 'Ext.app.ViewController',
    alias: 'controller.testcontroller',

    doSearch: function (field) {
        var list = this.lookup('list'),
            store = list.getStore(),
            value = field.getValue();

        if (Ext.isEmpty(value)) {
            store.removeFilter('firstName')
        } else {
            store.filter([{
                property: 'firstName',
                value: value,
                operator: 'like'
            }])
        }
    }
});

Ext.define('App.dataview.TestList', {
    extend: 'Ext.dataview.List',
    xtype: 'testlist',

    viewModel: {
        type: 'test'
    },

    plugins: [{
        type: 'pullrefresh',
        mergeData: false
    }],

    emptyText: 'Name not found',
    bind: {
        store: '{chained}'
    },
    itemTpl: '<div class="contact">{id} <b>{firstName} {lastName}</b></div>'
});

Ext.define('App.MainView', {
    extend: 'Ext.Panel',
    controller: 'testcontroller',
    fullscreen: true,

    viewModel: {
        type: 'test'
    },

    items: [{
        xtype: 'searchfield',
        ui: 'solo',
        placeholder: 'Search names',
        listeners: {
            buffer: 500,
            change: 'doSearch'
        },
        bind: {
            value: '{query}'
        }
    }, {
        reference: 'list',
        xtype: 'testlist'
    }]

})

Ext.application({
    name: 'App',

    mainView: 'App.MainView'
});

names.json

var data = [{
    id: 1,
    firstName: 'Peter',
    lastName: 'Venkman'
}, {
    id: 2,
    firstName: 'Raymond',
    lastName: 'Stantz'
}, {
    id: 3,
    firstName: 'Egon',
    lastName: 'Spengler'
}, {
    id: 4,
    firstName: 'Winston',
    lastName: 'Zeddemore'
}]

var results = data.filter(function(record) {
    if (params.filter) {
        return record.id > params.filter[0].value
    }
})

return {
    "success": true,
    "data": results
}

App.override.dataview.pullrefresh.PullRefresh:

Ext.define('App.override.dataview.pullrefresh.PullRefresh', {
  override: 'Ext.dataview.pullrefresh.PullRefresh',

  privates: {
    fetchLatest: function() {
      const store = this.getStore().isChainedStore ? this.getStore().getSource() : this.getStore()
      store.fetch({
          page: 1,
          start: 0,
          callback: this.onLatestFetched,
          scope: this
      });
    },

    onLatestFetched: function(newRecords, operation, success) {
      var me = this,
          list = me.getList(),
          store = list.getStore().isChainedStore ? list.getStore().getSource() : list.getStore(),
          length, toInsert,
          oldRecords, newRecord, oldRecord, i;

      if (success) {
          if (me.getMergeData()) {
              oldRecords = store.getData();
              toInsert = [];
              length = newRecords.length;

              for (i = 0; i < length; i++) {
                  newRecord = newRecords[i];
                  oldRecord = oldRecords.getByKey(newRecord.getId());

                  if (oldRecord) {
                      oldRecord.set(newRecord.getData());
                  }
                  else {
                      toInsert.push(newRecord);
                  }
              }

              store.insert(0, toInsert);
          }
          else {
              store.loadRecords(newRecords);
          }

          me.setLastUpdated(new Date());
      }

      me.setState('loaded');
      list.fireEvent('latestfetched', me, toInsert || newRecords);

      if (me.getAutoSnapBack()) {
          me.snapBack(true);
      }
    }
  }
})

提前致谢

由于此 post 不是一个问题,而是一个带有可能解决方案的错误报告,因此它已被 post 编辑到 Ext JS 7.x Community Forums\Ext JS 7.x Bugs

上面的解决方案覆盖了需要源存储的插件,如果有人遇到同样的问题,它是有效的。