extjs 组合框ext 4.0中的动态滚动

klh5stk1  于 2022-12-18  发布在  其他
关注(0)|答案(5)|浏览(184)

我使用extjs 4.0和有一个组合框与queryMode '远程'。我填写它与数据从服务器。问题是,记录的数量从服务器是太大了,所以我认为这将是更好地加载他们的部分。我知道有一个标准的分页工具组合框,但它是不方便的,因为需要记录总数。
有没有办法为组合框添加动态滚动?当滚动到列表底部时,我想发送下一部分记录的请求并将其添加到列表中。我找不到合适的侦听器来完成此操作。

iugsix8n

iugsix8n1#

下面是我为Extjs4.0组合框提供的无限滚动解决方案

Ext.define('TestProject.testselect', {
    extend:'Ext.form.field.ComboBox',
    alias: ['widget.testselect'],
    requires: ['Ext.selection.Model', 'Ext.data.Store'],

    /**
     * This will contain scroll position when user reaches the bottom of the list 
     * and the store begins to upload data
     */
    beforeRefreshScrollTop: 0,

    /**
     * This will be changed to true, when there will be no more records to upload
     * to combobox
     */
    isStoreEndReached : false,

    /**
     * The main thing. When creating picker, we add scroll listener on list dom element.
     * Also add listener on load mask - after load mask is hidden we set scroll into position 
     * that it was before new items were loaded to list. This prevents 'jumping' of the scroll.
     */
    createPicker: function() {
        var me = this,
        picker = me.callParent(arguments);
        me.mon(picker, {
            'render' : function() {
                Ext.get(picker.getTargetEl().id).on('scroll', me.onScroll, me);
                me.mon(picker.loadMask, {
                   'hide' : function() {
                      Ext.get(picker.id + '-listEl').scroll("down", me.beforeRefreshScrollTop, false);
                   },
                   scope: me
                });
            },
            scope: me
        });
        return picker;
    },

    /**
     * Method which is called when user scrolls the list. Checks if the bottom of the 
     * list is reached. If so - sends 'nextPage' request to store and checks if 
     * any records were received. If not - then there is no more records to load, and 
     * from now on if user will reach the bottom of the list, no request will be sent.
     */
    onScroll: function(){
        var me = this,
        parentElement = Ext.get(me.picker.getTargetEl().id),
        parentElementTop = parentElement.getScroll().top,
        scrollingList = Ext.get(me.picker.id+'-items');
        if(scrollingList != undefined) {
            if(!me.isStoreEndReached && parentElementTop >= scrollingList.getHeight() - parentElement.getHeight()) {
                var multiselectStore = me.getStore(),
                beforeRequestCount = multiselectStore.getCount();
                me.beforeRefreshScrollTop = parentElementTop;
                multiselectStore.nextPage({
                    params: this.getParams(this.lastQuery),
                    callback: function() {
                            me.isStoreEndReached = !(multiselectStore.getCount() - beforeRequestCount > 0);
                        }
                });
            }
        }
    },

    /**
     * Took this method from Ext.form.field.Picker to collapse only if 
     * loading finished. This solve problem when user scrolls while large data is loading.
     * Whithout this the list will close before finishing update.
     */
    collapse: function() {
        var me = this;
        if(!me.getStore().loading) {
            me.callParent(arguments);
        }
    },

    /**
     * Reset scroll and current page of the store when loading all profiles again (clicking on trigger)
     */
    doRawQuery: function() {
        var me = this;
        me.beforeRefreshScrollTop = 0;
        me.getStore().currentPage = 0;
        me.isStoreEndReached = false;
        me.callParent(arguments);
    }
});

当创建元素时,应该将id传递给listConfig,我也传递了list的模板,因为我需要它带有id。我没有找到更优雅的方法来做到这一点。我感谢任何建议。

{
                    id: 'testcombo-multiselect',
                    xtype: 'testselect',
                    store: Ext.create('TestProject.testStore'),
                    queryMode: 'remote',
                    queryParam: 'keyword',
                    valueField: 'profileToken',
                    displayField: 'profileToken',
                    tpl: Ext.create('Ext.XTemplate',
                        '<ul id="ds-profiles-boundlist-items"><tpl for=".">',
                            '<li role="option" class="' + Ext.baseCSSPrefix + 'boundlist-item' + '">',
                                '{profileToken}',
                            '</li>',
                        '</tpl></ul>'
                    ),
                    listConfig: {
                        id: 'testcombo-boundlist'
                    }
                },

和商店:

Ext.define('TestProject.testStore',{
    extend: 'Ext.data.Store',
    storeId: 'teststore',
    model: 'TestProject.testModel',
    pageSize: 13, //the bulk of records to receive after each upload
    currentPage: 0, //server side works with page numeration starting with zero
    proxy: {
        type: 'rest',
        url: serverurl,
        reader: 'json'
    },
    clearOnPageLoad: false //to prevent replacing list items with new uploaded items
});

20jt8wwn

20jt8wwn2#

感谢我为你指路。

Ext.define('utils.fields.BoundList', {
    override:'Ext.view.BoundList',
    ///@function utils.fields.BoundList.loadNextPageOnScroll
    ///Add scroll listener to load next page if true.
    ///@since 1.0
    loadNextPageOnScroll:true,
    ///@function utils.fields.BoundList.afterRender
    ///Add scroll listener to load next page if required.
    ///@since 1.0
    afterRender:function(){
        this.callParent(arguments);

        //add listener
        this.loadNextPageOnScroll
        &&this.getTargetEl().on('scroll', function(e, el){
            var store=this.getStore();
            var top=el.scrollTop;
            var count=store.getCount()
            if(top>=el.scrollHeight-el.clientHeight//scroll end
               &&count<store.getTotalCount()//more data
              ){
                  //track state
                  var page=store.currentPage;
                  var clearOnPageLoad=store.clearOnPageLoad;
                  store.clearOnPageLoad=false;

                  //load next page
                  store.loadPage(count/store.pageSize+1, {
                      callback:function(){//restore state
                          store.currentPage=page;
                          store.clearOnPageLoad=clearOnPageLoad;
                          el.scrollTop=top;
                      }
                  });
              }
        }, this);
    },
});
x4shl7ld

x4shl7ld3#

您可以将无限网格实现为组合框的列表。请看下面的示例来实现另一个选择器:
http://www.sencha.com/forum/showthread.php?132328-CLOSED-ComboBox-using-Grid-instead-of-BoundList

qmelpv7a

qmelpv7a4#

如果有人在ExtJS版本6中需要这个,下面是代码:

Ext.define('Test.InfiniteCombo', {
    extend: 'Ext.form.field.ComboBox',
    alias: ['widget.infinitecombo'],

    /**
     * This will contain scroll position when user reaches the bottom of the list
     * and the store begins to upload data
     */
    beforeRefreshScrollTop: 0,

    /**
     * This will be changed to true, when there will be no more records to upload
     * to combobox
     */
    isStoreEndReached: false,

    /**
     * The main thing. When creating picker, we add scroll listener on list dom element.
     * Also add listener on load mask - after load mask is hidden we set scroll into position
     * that it was before new items were loaded to list. This prevents 'jumping' of the scroll.
     */
    createPicker: function () {
        var me = this,
            picker = me.callParent(arguments);
        me.mon(picker, {
            'afterrender': function () {
                picker.on('scroll', me.onScroll, me);
                me.mon(picker.loadMask, {
                    'hide': function () {
                        picker.scrollTo(0, me.beforeRefreshScrollTop,false);
                    },
                    scope: me
                });
            },
            scope: me
        });
        return picker;
    },

    /**
     * Method which is called when user scrolls the list. Checks if the bottom of the
     * list is reached. If so - sends 'nextPage' request to store and checks if
     * any records were received. If not - then there is no more records to load, and
     * from now on if user will reach the bottom of the list, no request will be sent.
     */
    onScroll: function () {
        var me = this,
            parentElement = me.picker.getTargetEl(),
            scrollingList = Ext.get(me.picker.id + '-listEl');
        if (scrollingList != undefined) {
            if (!me.isStoreEndReached && me.picker.getScrollY() + me.picker.getHeight() > parentElement.getHeight()) {
                var store = me.getStore(),
                    beforeRequestCount = store.getCount();
                me.beforeRefreshScrollTop = me.picker.getScrollY();
                store.nextPage({
                    params: this.getParams(this.lastQuery),
                    callback: function () {
                        me.isStoreEndReached = !(store.getCount() - beforeRequestCount > 0);
                    }
                });
            }
        }
    },

    /**
     * Took this method from Ext.form.field.Picker to collapse only if
     * loading finished. This solve problem when user scrolls while large data is loading.
     * Whithout this the list will close before finishing update.
     */
    collapse: function () {
        var me = this;
        if (!me.getStore().loading) {
            me.callParent(arguments);
        }
    },

    /**
     * Reset scroll and current page of the store when loading all profiles again (clicking on trigger)
     */
    doRawQuery: function () {
        var me = this;
        me.beforeRefreshScrollTop = 0;
        me.getStore().currentPage = 1;
        me.isStoreEndReached = false;
        me.callParent(arguments);
    }
});
mrphzbgm

mrphzbgm5#

首先感谢@me1111发布了滚动条动态渲染的代码。在做了一些小的改动之后,这段代码对我来说是有用的。

tpl: Ext.create('Ext.XTemplate',
                    '<ul id="testcombo-boundlist-items"><tpl for=".">',
                        '<li role="option" class="' + Ext.baseCSSPrefix + 'boundlist-item' + '">',
                            '{profileToken}',
                        '</li>',
                    '</tpl></ul>'
                ),
                listConfig: {
                    id: 'testcombo-boundlist'
                }

<ul id="ds-profiles-boundlist-items"><tpl for=".">的代码中,我将ID更改为“testcombo-boundlist-items”,因为我们在listConfig中将ID定义为“testcombo-boundlist”。
在修改之前,在onScroll方法scrollingList = Ext.get(me.picker.id + '-items');中,我得到的scrollList为空。因为me.picker.id将在此返回“testcombo-boundlist”,所以我们附加了“-items”,所以它变成了“testcombo-boundlist-items”,但此ID不存在。所以我得到的是空。
修改<ul id="testcombo-boundlist-items">中的id后,我们在“testcombo-boundlist-items”上有了一个列表对象,所以我得到了一个对象。
希望这个小小的改变能有所帮助。

相关问题