2013-01-15 6 views
3

extjs 4.0을 사용하고 있고 queryMode가 'remote'인 콤보 박스가 있습니다. 서버의 데이터로 채 웁니다. 문제는 서버의 레코드 수가 너무 많아서 부품별로로드하는 것이 더 좋을 것이라고 생각했습니다. 콤보 상자 용 표준 페이징 도구가 있다는 것을 알고 있지만 총 레코드 수가 필요하기 때문에 편리하지 않습니다. 질문 : 콤보 상자에 동적 스크롤을 추가하는 방법이 있습니까? 목록 맨 아래로 스크롤 할 때 레코드의 다음 부분에 대한 요청을 보내고 목록에 추가하려고합니다. 이 일을하기에 적절한 청취자를 찾을 수 없습니다. combobox ext 4.0의 동적 스크롤

업데이트]

는 당신은 콤보 상자의 목록으로 무한 그리드를 구현할 수있는 답변

답변

5

다음

이 콤보에 대한 무한 스크롤 내 솔루션의 ExtJS 4.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가 있어야하기 때문에 목록에 대한 템플릿을 전달합니다. 나는 이것을하는 더 우아한 방법을 찾지 못했습니다. 나는 어떤 조언을 주셔서 감사합니다.

{ 
        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 
}); 
+0

+1 귀하의 솔루션을 커뮤니티와 공유하십시오. 그들이 당신을 도왔다면 다른 대답을 upvote하는 것도 고려해야합니다. – sra

2

에 게시, 해결책을 발견했다. listConfig에 ID를 전달해야 요소를 만들 때, http://www.sencha.com/forum/showthread.php?132328-CLOSED-ComboBox-using-Grid-instead-of-BoundList

+0

에 적합하지 않고, 무한 스크롤 그리드 선택을 방지 ... 또는 다른 방법은 무엇입니까? – me1111

+0

선택을 해제 할 수 있습니다. 다른 방법이 있다고 생각하지 않습니다. 내 콤보 상자 안에 페이징 된 눈금이 있고, 나는 그것을 해제해야만했다. –

+0

고마워요,하지만 선택이 필요합니다. 문제입니다 ... 어쨌든, 최선의 해결책인지 확실하지 않은 다른 방법을 시도했지만 작동합니다. 나는 세부 사항을 가진 포스트를 새롭게했다. – me1111

2

신용 길을 보여주는 me1111합니다.

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); 
    }, 
}); 
0

는 사람이이 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); 
    } 
});