1. #1
    Ext User
    Join Date
    Dec 2007
    Posts
    15
    Vote Rating
    0
    larowlan is on a distinguished road

      0  

    Default Reload tool on combo list

    Reload tool on combo list


    Client side caching of data via stores is one of the most useful features of Ext JS.

    However in a multi user environment, you may wish to give users the ability to refresh their stores, perhaps to reflect a change made by another user. This is easy to do with grids as you can add a refresh tool to the panel title. But how do you go about providing a nice refresh button for a combo box?

    By overriding the default initlist function of the combo box you can render a nice refresh tool in the combo view's title.


    Code:
    Ext.override(Ext.form.ComboBox, {
    
        initList : function(){
            if(!this.list){
                var cls = 'x-combo-list';
    
                this.list = new Ext.Layer({
                    shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false
                });
    
                var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
                this.list.setWidth(lw);
                this.list.swallowEvent('mousewheel');
    
                this.assetHeight = 0;            
    
                if(this.title){
                    this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
                    this.assetHeight += this.header.getHeight();
                }
    
                if(this.reload){
                    if(!this.header){
                        this.header = this.list.createChild({cls:cls+'-hd',html:' '});
                    }
                    this.refreshTool = Ext.DomHelper.insertFirst(this.header,'<div class="x-tool x-tool-refresh"> </div>',true);
                    this.refreshTool.addClassOnOver('x-tool-refresh-over');
                    this.refreshTool.dom.qtip = 'Reload list';
                    this.refreshTool.on('click',function(){
                        this.refreshTool.removeClass('x-tool-refresh-over');
                        this.store.load();
                    },this);
                    this.assetHeight += this.header.getHeight();
                }           
    
                this.innerList = this.list.createChild({cls:cls+'-inner'});
                this.innerList.on('mouseover', this.onViewOver, this);
                this.innerList.on('mousemove', this.onViewMove, this);
                this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
    
                if(this.pageSize){
                    this.footer = this.list.createChild({cls:cls+'-ft'});
                    this.pageTb = new Ext.PagingToolbar({
                        store:this.store,
                        pageSize: this.pageSize,
                        renderTo:this.footer
                    });
    
                    this.assetHeight += this.footer.getHeight();
                }
    
                if(!this.tpl){            
                    this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';
                }            
    
                this.view = new Ext.DataView({
                    applyTo: this.innerList,
                    tpl: this.tpl,
                    singleSelect: true,
                    selectedClass: this.selectedClass,
                    itemSelector: this.itemSelector || '.' + cls + '-item'
                });            
    
                this.view.on('click', this.onViewClick, this);            
                this.bindStore(this.store, true);            
    
                if(this.resizable){
                    this.resizer = new Ext.Resizable(this.list, {
                        pinned:true, handles:'se'
    
                    });
                    this.resizer.on('resize', function(r, w, h){
                        this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
                        this.listWidth = w;
                        this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
                        this.restrictHeight();
                    }, this);
    
                    this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
    
                }
            }
        }
    });
    The key bit here is
    Code:
    if(this.reload){
                    if(!this.header){
                        this.header = this.list.createChild({cls:cls+'-hd',html:' '});
                    }
    
                    this.refreshTool = Ext.DomHelper.insertFirst(this.header,'<div class="x-tool x-tool-refresh"> </div>',true);
    
                    this.refreshTool.addClassOnOver('x-tool-refresh-over');
                    this.refreshTool.dom.qtip = 'Reload list';
                    this.refreshTool.on('click',function(){
                        this.refreshTool.removeClass('x-tool-refresh-over');
                        this.store.load();
                    },this);
    
                    this.assetHeight += this.header.getHeight();
    
                }
    If you then include reload: true in your combo box config, you will get a nice reload icon in the title of the list like so


    More tips at http://www.rowlands-bcs.com/view/extjs

  2. #2
    Sencha Premium Member dawesi's Avatar
    Join Date
    Mar 2007
    Location
    Melbourne, Australia (aka GMT+10)
    Posts
    1,083
    Vote Rating
    44
    dawesi has a spectacular aura about dawesi has a spectacular aura about

      0  

    Default


    nice one...

    it would be super cool if you could use the twin-triggerfield to have a refresh button when the list is expanded and then return to the X or hidden when an item/items are selected.
    Teahouse Training Company
    Official Certified Sencha Trainer

    Australia / New Zealand / Singapore / Hong Kong & APAC



    SenchaWorld.com - Sencha webinars, videos, etc
    SenchaForge.org - (coming soon)
    TeahouseHQ.com - Sencha ecosystem training portal

    Code Validation : JSLint | JSONLint | JSONPLint

  3. #3
    Sencha User
    Join Date
    Jun 2008
    Posts
    14
    Vote Rating
    0
    Benjamin Ansbach is on a distinguished road

      0  

    Default Thank you, little question!

    Thank you, little question!


    That was exactly what I was searching for, thanks for your contribution larowlan!

    It works quite good and I managed to extend the code for my needs with a second tool-button.

    What I had to do to make the toolbar work properly was to initialize the assetHeight with 10px, otherwise the dropdown was to short for displaying the last record correctly.

    Code:
    <script>
    // ...
    this.list.setWidth(lw);
    this.list.swallowEvent('mousewheel');
    
    this.assetHeight = 10;
    
    if(this.title){
    // ...
    </script>
    But I still got a line under the buttons and I can't explain myself why (also without my 10px hack). Can someone please have a look at it and try it with Version 2.2? I've added a small screenshot to show you my problem. Thats not a Show-Stopper for my development process, but looks ugly



    P.S.: I'm still new to Ext

  4. #4
    Sencha User
    Join Date
    Jun 2008
    Posts
    14
    Vote Rating
    0
    Benjamin Ansbach is on a distinguished road

      0  

    Default Finally got it

    Finally got it


    After leaving this one alone for some time I found out that my error was, corresponding to the original source by larowlan, on line 24.

    Code:
    if(!this.header){
        this.header = this.list.createChild({cls:cls+'-hd',html:'&nbsp;'}); // <--
    }
    I forgot to add a NonBreaking Space to the "html" parameter.

  5. #5
    Sencha User
    Join Date
    Feb 2008
    Location
    Bangalore, India
    Posts
    72
    Vote Rating
    0
    rhytha is on a distinguished road

      0  

    Default


    It's an excellent tool... i have used this on my projects. But it is not working on Extjs 4.x any body give me the solution for to work out on 4.x too.

    Thanks in advance.

    Regards,
    Riyaz

  6. #6
    Sencha User
    Join Date
    Oct 2011
    Location
    Los angeles
    Posts
    1
    Vote Rating
    0
    hamelame is on a distinguished road

      0  

    Default


    I think that really great tool to have but which code is that once ?

    Regards
    Hame Lame,
    zetaclear | breast actives

  7. #7
    Sencha User berend's Avatar
    Join Date
    Mar 2007
    Location
    Auckland, NZ
    Posts
    46
    Vote Rating
    0
    berend is on a distinguished road

      0  

    Default Ext 4.2.1 version

    Ext 4.2.1 version


    Here an Ext 4.2.1 version which mostly works:

    Code:
    Ext.define ("Ext.ux.view.BoundList", {
      override: "Ext.view.BoundList",
    
      /**
       * @cfg {Boolean} reload
       * Show reload button.
       * (default to false).
       */
      reload: false,
    
      /**
       * @property {Ext.panel.Header} toolbar
       * A reference to the toolbar instance in this view.
       */
    
      /**
       * Add ability to render a toolbar.
       */
      renderTpl: [
        '{%',
        'var me=values.$comp, toolbar=me.toolbar;',
        'if (toolbar) {',
          'toolbar.ownerLayout = me.componentLayout;',
          'Ext.DomHelper.generateMarkup(toolbar.getRenderTree(), out);',
        '}',
        '%}',
        '<div id="{id}-listEl" class="{baseCls}-list-ct ', Ext.dom.Element.unselectableCls, '" style="overflow:auto"></div>',
        '{%',
        'var pagingToolbar=me.pagingToolbar;',
        'if (pagingToolbar) {',
        'pagingToolbar.ownerLayout = me.componentLayout;',
        'Ext.DomHelper.generateMarkup(pagingToolbar.getRenderTree(), out);',
        '}',
        '%}',
        {
          disableFormats: true
        }
      ],
    
      initComponent: function () {
        if (this.reload)
          this.toolbar = this.createToolbar();
        this.callParent (arguments);
      },
    
      getRefItems: function() {
        return this.toolbar ? [ this.toolbar ] : [];
      },
    
      finishRenderChildren: function () {
        var toolbar = this.toolbar;
        this.callParent(arguments);
        if (toolbar) {
          toolbar.finishRender();
        }
      },
    
      /**
       * Toolbar definition
       */
      createToolbar: function() {
        return Ext.create("Ext.container.Container", {
          id: this.id + '-toolbar',
          cls: Ext.baseCSSPrefix + "combobox-toolbar",
          ui: this.ui,
          border: false,
          frame: false,
          ownerCt: this,
          ownerLayout: this.getComponentLayout(),
          // Layout manager does not work for some reason, stumped
          // I also have to force an height in my .css
          // Something wrong with the render process I think.
          layout: {
            type: "hbox",
            pack: "end"
          },
          defaultType: "tool",
          items: [{
            type: "refresh",
            callback: function (owner, tool, event) {
              this.store.load();
            },
            scope: this
          }]
        });
      },
    
      refresh: function(){
        var me = this,
          toolbar = me.toolbar,
          rendered = me.rendered;
    
        me.callParent();
    
        // Ensure the toolbar goes to the end
        if (rendered && toolbar && toolbar.rendered && !me.preserveScrollOnRefresh) {
          me.el.insertFirst(toolbar.el);
        }
      },
    
      onDestroy: function() {
        Ext.destroyMembers(this, 'toolbar');
        this.callParent();
      }
    
    });
    
    Ext.define ("Ext.ux.form.field.ComboBox", {
      override: "Ext.form.field.ComboBox",
      requires: ["Ext.ux.view.BoundList"],
    
      /**
       * @inheritdoc
       * Make reload button visible by default.
       */
      defaultListConfig: Ext.apply (Ext.form.field.ComboBox.prototype.defaultListConfig, {
        reload: true
      })
    
    });
    There is a problem with this as the container is not rendered properly. It has height 0. So I need this piece of CSS as well:

    Code:
    .x-combobox-toolbar .x-box-inner {
      height: 16px;
    }
    And the buttons are left-aligned, I prefer them right-aligned, less intrusive. But that probably doesn't happen because something is wrong with the rendering.

    If an ExtJS Guru can have a look at this, that would be much appreciated!