1. #31
    Ext User
    Join Date
    Jul 2007
    Location
    Florida
    Posts
    9,996
    Vote Rating
    6
    mjlecomte will become famous soon enough mjlecomte will become famous soon enough

      0  

    Default


    @renoye and @yoda suggest you post working code for testing

  2. #32
    Ext User tonedeaf's Avatar
    Join Date
    Dec 2007
    Posts
    137
    Vote Rating
    1
    tonedeaf is on a distinguished road

      0  

    Default Dynamically loading numeric filters

    Dynamically loading numeric filters


    I'm trying to load filters dynamically where a user could filter a grid and then save it as a "view". So, when the "view" is opened, the filters are fetched from the server and applied to the grid.

    For this, I'm using the GridFilters addFilter() function and pass it a filter configuration with a value like:
    Code:
    [{"dataIndex":"company", "type":"string", "value":"Washington Mutual"}]
    The GridFilters UI gets correctly updated and the filter is applied (and sent back to the server on subsequent refreshes.)

    The addFilter() function works fine with filters of type "list", "string" and "boolean" (not tested with "date" type yet).

    Now, I'm facing a problem with using addFilter() function for dynamically adding "numeric" filters. For eg:
    Code:
    [{"dataIndex":"age", "type":"numeric", "comparison":"eq", "value":"27"}]
    doesn't throw any error when passed to addFilter(), but the filter is not "shown" in the UI. However, the column header background turns green (which shows that the function "tries" to apply the filter value). But the filter is never sent back to the server for subsequent refreshes.

    This problem is identical to the following post for GridFilters 2.x posted an year back and the same issue is visible in the ExtJS 3.x version of the extension.
    http://www.extjs.com/forum/showthrea...531#post230531

    Can anyone suggest a remedy? I think its a bug in GridFilters and the issue has to do with the GridFilters RangeMenu not correctly getting updated.

    Unfortunately, I'm not too familiar with the internals of the GridFilters plugin to fix this myself.

    EDIT: Figured out the correct configuration format for numeric filters:
    Code:
    [{"dataIndex":"age", "type":"numeric", "value":{"eq":"27"}}]

  3. #33
    Sencha User calavera's Avatar
    Join Date
    Jan 2008
    Posts
    119
    Vote Rating
    0
    calavera is on a distinguished road

      0  

    Default


    Anybody willing to share the PHP backend code for this ? The Ext 2 code for this doesn't work anymore.

    Thanks.

  4. #34
    Sencha - Community Support Team VinylFox's Avatar
    Join Date
    Mar 2007
    Location
    Baltimore, MD
    Posts
    1,501
    Vote Rating
    8
    VinylFox will become famous soon enough VinylFox will become famous soon enough

      0  

    Default


    The backend code works fine for me.

  5. #35
    Ext User
    Join Date
    Jul 2009
    Posts
    1
    Vote Rating
    0
    RanmaSaotome is on a distinguished road

      0  

    Default Little fix when paging-toolbar is not updated after reconfigure

    Little fix when paging-toolbar is not updated after reconfigure


    Hello,
    I had the problem that once I reconfigured my grid (especially using a new store), the pagingtoolbar was not updated any more. Maybe this problem has already been fixed, but I did not find anything in the forum so far:

    Hotfix:

    In GridFilters.js:

    Code:
    onReconfigure : function() {
        this.bindStore(this.grid.getStore());
        this.store.clearFilter();
        this.removeAll();
        this.addFilters(this.grid.getColumnModel());
        this.updateColumnHeadings();
    +++    if (this.toolbar) this.toolbar.bindStore(this.store, true);
    },
    Best wishes,

    Ranma

  6. #36
    Sencha User calavera's Avatar
    Join Date
    Jan 2008
    Posts
    119
    Vote Rating
    0
    calavera is on a distinguished road

      0  

    Default


    Quote Originally Posted by VinylFox View Post
    The backend code works fine for me.
    Oh, I had "encode:true" at my setup. Changed to false. Thanks.

  7. #37
    Sencha User benmclendon's Avatar
    Join Date
    Jul 2008
    Location
    Valdosta, GA
    Posts
    70
    Vote Rating
    1
    benmclendon is on a distinguished road

      0  

    Default


    @drieraf

    Many Thanks! This worked perfectly for me with 3.0.0 code.

    Quote Originally Posted by drieraf View Post
    Hi. I'm agree with you, but I patched the old code with forum comments. I think that run correctly.

    Code:
    /**
     * Ext.ux.grid.GridFilters v0.2.8
     **/
    
    Ext.namespace("Ext.ux.grid");
    /* PATCH http://extjs.com/forum/showthread.php?t=76280 */
    Ext.override(Ext.grid.GridView, {
        handleHdMenuClick : function(item){
            var index = this.hdCtxIndex,
                cm = this.cm, 
                ds = this.ds,
                id = item.getItemId();
            switch(id){
                case 'asc':
                    ds.sort(cm.getDataIndex(index), 'ASC');
                    break;
                case 'desc':
                    ds.sort(cm.getDataIndex(index), 'DESC');
                    break;
                default:
                    index = cm.getIndexById(id.substr(4));
                    if(index != -1){
                        if(item.checked && cm.getColumnsBy(this.isHideableColumn, this).length <= 1){
                            this.onDenyColumnHide();
                            return false;
                        }
                        cm.setHidden(index, item.checked);
                    }
            }
            return true;
        }
    });
    /* END PATCH */
    Ext.ux.grid.GridFilters = function(config){        
        this.filters = new Ext.util.MixedCollection();
        this.filters.getKey = function(o){return o ? o.dataIndex : null};
        
        for(var i=0, len=config.filters.length; i<len; i++)
            this.addFilter(config.filters[i]);
        
        this.deferredUpdate = new Ext.util.DelayedTask(this.reload, this);
        
        delete config.filters;
        Ext.apply(this, config);
    };
    Ext.extend(Ext.ux.grid.GridFilters, Ext.util.Observable, {
        /**
         * @cfg {Integer} updateBuffer
         * Number of milisecond to defer store updates since the last filter change.
         */
        updateBuffer: 500,
        /**
         * @cfg {String} paramPrefix
         * The url parameter prefix for the filters.
         */
        paramPrefix: 'filter',
        /**
         * @cfg {String} fitlerCls
         * The css class to be applied to column headers that active filters. Defaults to 'ux-filterd-column'
         */
        filterCls: 'ux-filtered-column',
        /**
         * @cfg {Boolean} local
         * True to use Ext.data.Store filter functions instead of server side filtering.
         */
        local: false,
        /**
         * @cfg {Boolean} autoReload
         * True to automagicly reload the datasource when a filter change happens.
         */
        autoReload: true,
        /**
         * @cfg {String} stateId
         * Name of the Ext.data.Store value to be used to store state information.
         */
        stateId: undefined,
        /**
         * @cfg {Boolean} showMenu
         * True to show the filter menus
         */
        showMenu: true,
    
        menuFilterText: 'Filters',
    
        init: function(grid){
            if(grid instanceof Ext.grid.GridPanel){
                this.grid  = grid;
              
                this.store = this.grid.getStore();
                if(this.local){
                    this.store.on('load', function(store){
                        store.filterBy(this.getRecordFilter());
                    }, this);
                } else {
                  this.store.on('beforeload', this.onBeforeLoad, this);
                }
                  
                this.grid.filters = this;
                 
                this.grid.addEvents({"filterupdate": true});
                  
                grid.on("render", this.onRender, this);
                  
                grid.on("beforestaterestore", this.applyState, this);
                grid.on("beforestatesave", this.saveState, this);
                          
            } else if(grid instanceof Ext.PagingToolbar){
              this.toolbar = grid;
            }
        },
            
        /** private **/
        applyState: function(grid, state){
            this.suspendStateStore = true;
            this.clearFilters();
            if(state.filters)
                for(var key in state.filters){
                    var filter = this.filters.get(key);
                    if(filter){
                        filter.setValue(state.filters[key]);
                        filter.setActive(true);
                    }
                }
                
            this.deferredUpdate.cancel();
            if(this.local)
                this.reload();
                
            this.suspendStateStore = false;
        },
        
        /** private **/
        saveState: function(grid, state){
            var filters = {};
            this.filters.each(function(filter){
                if(filter.active)
                    filters[filter.dataIndex] = filter.getValue();
            });
            return state.filters = filters;
        },
        
        /** private **/
        onRender: function(){
            var hmenu;
            
            if(this.showMenu){
                hmenu = this.grid.getView().hmenu;
                
                this.sep  = hmenu.addSeparator();
                this.menu = hmenu.add(new Ext.menu.CheckItem({
                        text: this.menuFilterText,
                        menu: new Ext.menu.Menu()
                    }));
                this.menu.on('checkchange', this.onCheckChange, this);
                this.menu.on('beforecheckchange', this.onBeforeCheck, this);
                    
                hmenu.on('beforeshow', this.onMenu, this);
            }
            
            this.grid.getView().on("refresh", this.onRefresh, this);
            this.updateColumnHeadings(this.grid.getView());
        },
        
        /** private **/
        onMenu: function(filterMenu){
            var filter = this.getMenuFilter();
            if(filter){
                this.menu.menu = filter.menu;
                this.menu.setChecked(filter.active, false);
            }
            
            this.menu.setVisible(filter !== undefined);
            this.sep.setVisible(filter !== undefined);
        },
        
        /** private **/
        onCheckChange: function(item, value){
            this.getMenuFilter().setActive(value);
        },
        
        /** private **/
        onBeforeCheck: function(check, value){
            return !value || this.getMenuFilter().isActivatable();
        },
        
        /** private **/
        onStateChange: function(event, filter){
        if(event == "serialize") return;
        
            if(filter == this.getMenuFilter())
                this.menu.setChecked(filter.active, false);
                
            if(this.autoReload || this.local)
                this.deferredUpdate.delay(this.updateBuffer);
            
            var view = this.grid.getView();
            this.updateColumnHeadings(view);
                
            this.grid.saveState();
                
            this.grid.fireEvent('filterupdate', this, filter);
        },
        
        /** private **/
        onBeforeLoad: function(store, options){
        options.params = options.params || {};
            this.cleanParams(options.params);        
            var params = this.buildQuery(this.getFilterData());
            Ext.apply(options.params, params);
        },
        
        /** private **/
        onRefresh: function(view){
            this.updateColumnHeadings(view);
        },
        
        /** private **/
        getMenuFilter: function(){
            var view = this.grid.getView();
            if(!view || view.hdCtxIndex === undefined)
                return null;
            
            return this.filters.get(
                view.cm.config[view.hdCtxIndex].dataIndex);
        },
        
        /** private **/
        updateColumnHeadings: function(view){
            if(!view || !view.mainHd) return;
            
            var hds = view.mainHd.select('td').removeClass(this.filterCls);
            for(var i=0, len=view.cm.config.length; i<len; i++){
                var filter = this.getFilter(view.cm.config[i].dataIndex);
                if(filter && filter.active)
                    hds.item(i).addClass(this.filterCls);
            }
        },
        
        /** private **/
        reload: function(){
            if(this.local){
                this.grid.store.clearFilter(true);
                this.grid.store.filterBy(this.getRecordFilter());
            } else {
                this.deferredUpdate.cancel();
                var store = this.grid.store;
                if(this.toolbar){
                    var start = this.grid.getStore().paramNames.start;
                    if(store.lastOptions && store.lastOptions.params && store.lastOptions.params[start])
                        store.lastOptions.params[start] = 0;
                }
                store.reload();
            }
        },
        
        /**
         * Method factory that generates a record validator for the filters active at the time
         * of invokation.
         * 
         * @private
         */
        getRecordFilter: function(){
            var f = [];
            this.filters.each(function(filter){
                if(filter.active) f.push(filter);
            });
            
            var len = f.length;
            return function(record){
                for(var i=0; i<len; i++)
                    if(!f[i].validateRecord(record))
                        return false;
                    
                return true;
            };
        },
        
        /**
         * Adds a filter to the collection.
         * 
         * @param {Object/Ext.ux.grid.filter.Filter} config A filter configuration or a filter object.
         * 
         * @return {Ext.ux.grid.filter.Filter} The existing or newly created filter object.
         */
        addFilter: function(config){
            var filter = config.menu ? config : 
                    new (this.getFilterClass(config.type))(config);
            this.filters.add(filter);
            
            Ext.util.Observable.capture(filter, this.onStateChange, this);
            return filter;
        },
        
        /**
         * Returns a filter for the given dataIndex, if on exists.
         * 
         * @param {String} dataIndex The dataIndex of the desired filter object.
         * 
         * @return {Ext.ux.grid.filter.Filter}
         */
        getFilter: function(dataIndex){
            return this.filters.get(dataIndex);
        },
    
        /**
         * Turns all filters off. This does not clear the configuration information.
         */
        clearFilters: function(){
            this.filters.each(function(filter){
                filter.setActive(false);
            });
        },
    
        /** private **/
        getFilterData: function(){
            var filters = [],
                fields  = this.grid.getStore().fields;
            
            this.filters.each(function(f){
                if(f.active){
                    var d = [].concat(f.serialize());
                    for(var i=0, len=d.length; i<len; i++)
                        filters.push({
                            field: f.dataIndex,
                            data: d[i]
                        });
                }
            });
            
            return filters;
        },
        
        /**
         * Function to take structured filter data and 'flatten' it into query parameteres. The default function
         * will produce a query string of the form:
         *         filters[0][field]=dataIndex&filters[0][data][param1]=param&filters[0][data][param2]=param...
         * 
         * @param {Array} filters A collection of objects representing active filters and their configuration.
         *       Each element will take the form of {field: dataIndex, data: filterConf}. dataIndex is not assured
         *    to be unique as any one filter may be a composite of more basic filters for the same dataIndex.
         * 
         * @return {Object} Query keys and values
         */
        buildQuery: function(filters){
            var p = {};
            for(var i=0, len=filters.length; i<len; i++){
                var f    = filters[i];
                var root = [this.paramPrefix, '[', i, ']'].join('');
                p[root + '[field]'] = f.field;
                
                var dataPrefix = root + '[data]';
                for(var key in f.data)
                    p[[dataPrefix, '[', key, ']'].join('')] = f.data[key];
            }
            
            return p;
        },
        
        /**
         * Removes filter related query parameters from the provided object.
         * 
         * @param {Object} p Query parameters that may contain filter related fields.
         */
        cleanParams: function(p){
            var regex = new RegExp("^" + this.paramPrefix + "\[[0-9]+\]");
            for(var key in p)
                if(regex.test(key))
                    delete p[key];
        },
        
        /**
         * Function for locating filter classes, overwrite this with your favorite
         * loader to provide dynamic filter loading.
         * 
         * @param {String} type The type of filter to load.
         * 
         * @return {Class}
         */
        getFilterClass: function(type){
            return Ext.ux.grid.filter[type.substr(0, 1).toUpperCase() + type.substr(1) + 'Filter'];
        }
    });
    Ben McLendon
    IT Manager and part-time: coder, photographer, designer, etc...
    Centos(rackspace), Apache, MySQL, PHP, ExtJS,OSX
    http://www.linkedin.com/in/benmclendon
    http://www.barneshc.com
    - http://www.audiedigitalmedia.com

  8. #38
    Ext JS Premium Member
    Join Date
    May 2007
    Posts
    46
    Vote Rating
    1
    fshort is on a distinguished road

      0  

    Default Documentation

    Documentation


    Any chance we can get the documentation for Ext.grid.GridFilter integrated with the core Ext API? Dont see that there in any of the versions.

  9. #39
    Ext User
    Join Date
    Jul 2007
    Location
    Florida
    Posts
    9,996
    Vote Rating
    6
    mjlecomte will become famous soon enough mjlecomte will become famous soon enough

      0  

    Default


    Quote Originally Posted by fshort View Post
    Any chance we can get the documentation for Ext.grid.GridFilter integrated with the core Ext API? Dont see that there in any of the versions.
    You can already see it in 3.0.1.

  10. #40
    Ext User tonedeaf's Avatar
    Join Date
    Dec 2007
    Posts
    137
    Vote Rating
    1
    tonedeaf is on a distinguished road

      0  

    Default


    In GridFilters.css the CSS rule:
    Code:
    li.x-menu-list-item div {
        display:inline;
    }
    causes the month picker top to go out of the container. On removing this CSS rule, the month picker drop down shows correctly.


Thread Participants: 84

  1. VinylFox (1 Post)
  2. galdaka (2 Posts)
  3. Condor (10 Posts)
  4. cgi-bin (4 Posts)
  5. Fabyo (8 Posts)
  6. fshort (1 Post)
  7. digitalkaoz (1 Post)
  8. steffenk (2 Posts)
  9. brookd (1 Post)
  10. jamie.nicholson (1 Post)
  11. sawan (1 Post)
  12. froamer (1 Post)
  13. jaquet (1 Post)
  14. KevinChristensen (1 Post)
  15. bernd01 (2 Posts)
  16. tonedeaf (7 Posts)
  17. seg (1 Post)
  18. calavera (5 Posts)
  19. httpdotcom (1 Post)
  20. Timido (3 Posts)
  21. mfrancey (1 Post)
  22. WixSL (1 Post)
  23. drieraf (1 Post)
  24. nickweavers (2 Posts)
  25. goofy (1 Post)
  26. mynameisyoda (1 Post)
  27. manilodisan (1 Post)
  28. eyetv (1 Post)
  29. renoye (3 Posts)
  30. pouniok (2 Posts)
  31. mcouillard (6 Posts)
  32. Scorpie (1 Post)
  33. wiznia (1 Post)
  34. fulfowi (2 Posts)
  35. benmclendon (1 Post)
  36. roemisch (2 Posts)
  37. zeruyo (1 Post)
  38. dizor (1 Post)
  39. SunWuKung (5 Posts)
  40. mx_starter (1 Post)
  41. jimtyp (2 Posts)
  42. nitingautam (1 Post)
  43. westy (2 Posts)
  44. slemiere (1 Post)
  45. mike2406 (2 Posts)
  46. msinn (12 Posts)
  47. RanmaSaotome (1 Post)
  48. cnicolas (2 Posts)
  49. lsaffre (1 Post)
  50. astraschedule (1 Post)
  51. hankin (2 Posts)
  52. mrinaljena (1 Post)
  53. dtex-lab (1 Post)
  54. yohnan (2 Posts)
  55. Override (2 Posts)
  56. hjones (1 Post)
  57. hexawing (1 Post)
  58. taronja (6 Posts)
  59. asbestos girl (7 Posts)
  60. stalek (1 Post)
  61. mpawlowski (1 Post)
  62. DerSalz (1 Post)
  63. jimm (1 Post)
  64. blueberrymuffins (2 Posts)
  65. gleskinen (1 Post)
  66. pmdarrow (1 Post)
  67. Fallen Zen (1 Post)
  68. filippo.ferrari (6 Posts)
  69. george4rotech (2 Posts)
  70. Ebpo (1 Post)
  71. Reimius (1 Post)
  72. webtime (9 Posts)
  73. Christiand (1 Post)
  74. Oliver Specht (1 Post)
  75. novaku (1 Post)
  76. sizemorew (1 Post)
  77. # eof (1 Post)
  78. ldonofrio (3 Posts)
  79. david777 (1 Post)
  80. ExTriqui (4 Posts)
  81. leowyatt (7 Posts)
  82. JSassy (1 Post)
  83. hachie (1 Post)
  84. radmila80 (1 Post)