1. #1
    Sencha Premium Member d.zucconi's Avatar
    Join Date
    Jun 2008
    Location
    Piacenza (Italy)
    Posts
    78
    Vote Rating
    5
    d.zucconi is on a distinguished road

      5  

    Default Grid Header Filters

    Grid Header Filters


    This is the ExtJS 4 version of ExtJS 3.x plugin Ext.ux.grid.GridHeaderFilters available on thread
    http://www.sencha.com/forum/showthread.php?41658-Grid-header-filters
    The plugin has been rewritten to be compatible with the new ExtJS version and now works directly on new Ext.data.Store filters, using Ext.util.Filter objects.
    This is only a preview release for now, tested on FF,Chrome and IE9 with local and remote stores.
    Some functions will be improved in future versions.

    Source code
    Preview release - 14/10/11
    16/10/11 - Fixed resizeFilterContainer method (thanks to bsot)
    17/10/11 - Modified beforeheaderfiltersapply event handler result management (thanks to bsot)
    18/10/11 - Fixed wrong variable name in setFieldValue method code

    Version 0.1.0 - 04/11/11
    Modified events parameters adding the number of active (not empty) filters
    Added adjustFilterWidth on grid afterlayout event (thanks to zaggi
    )

    Version 0.2.0 - 05/03/12
    Changed plugin class name (Ext.ux.grid.plugin.HeaderFilters)
    Filters are rendered on headerCt afterrender event (thanks to puja for the hint)
    Modified adjustFilterWidth checking if containers are ready (thanks to Jad
    )
    Filter values are parsed only if the corresponding field isValid
    Adjusted filters tooltip
    Configurable status property for stateful filter values

    Code:
    /**
     * Plugin that enable filters on the grid header.<br>
     * The header filters are integrated with new Ext4 <code>Ext.data.Store</code> filters.<br>
     * It enables:
     * <ul>
     * <li>Instances of <code>Ext.form.field.Field</code> subclasses that can be used as filter fields into column header</li>
     * <li>New grid methods to control header filters (get values, update, apply)</li>
     * <li>New grid events to intercept plugin and filters events</li>
     * </ul>
     * 
     * The plugins also enables the stateful feature for header filters so filter values are stored with grid status if grid is stateful.<br>
     * 
     * # Enable filters on grid columns
     * The plugin checks the <code>filter</code> attribute that can be included into each column configuration.
     * The value of this attribute can be a <code>Ext.form.field.Field</code> configuration or an array of field configurations to enable more
     * than one filter on a single column.<br>
     * Field <code>readOnly</code> and <code>disabled</code> attributes are managed by the plugin to avoid filter update or filter apply.
     * The filter field configuration also supports some special attributes to control filter configuration:
     * <ul>
     * <li>
     *     <code>filterName</code>: the name of the filter that will be used when the filter is applied to store filters (as <code>property</code> of <code>Ext.util.Filter</code> attribute).
     *     If this attribute is not specified the column <code>dataIndex</code> will be used. <b>NOTE</b>: The filter name must be unique in a grid header. The plugin doesn't support correctly filters
     *     with same name.
     * </li>
     * </ul>
     * On the grid configuration the {@link #headerFilters} attribute is supported. The value must be an object with name-values pairs for filters to initialize. 
     * It can be used to initialize header filters in grid configuration.
     * 
     * # Plugin configuration
     * The plugin supports also some configuration attributes that can be specified when the plugin is created (with <code>Ext.create</code>).
     * These parameters are:
     * <ul>
     * <li>{@link #stateful}: Enables filters save and load when grid status is managed by <code>Ext.state.Manager</code>. If the grid is not stateful this parameter has no effects</li>
     * <li>{@link #reloadOnChange}: Intercepts the special {@link #headerfilterchange} plugin-enabled grid event and automatically reload or refresh grid Store. Default true</li>
     * <li>{@link #ensureFilteredVisible}: If one filter on column is active, the plugin ensures that this column is not hidden (if can be made visible).</li>
     * <li>{@link #enableTooltip}: Enable active filters description tootip on grid header</li>
     * </ul>
     * 
     * # Enabled grid methods
     * <ul>
     *     <li><code>setHeaderFilter(name, value, reset)</code>: Set a single filter value</li>
     *     <li><code>setHeaderFilters(filters, reset)</code>: Set header filters</li>
     *     <li><code>getHeaderFilters()</code>: Set header filters</li>
     *     <li><code>getHeaderFilterField(filterName)</code>: To access filter field</li>
     *     <li><code>resetHeaderFilters()</code>: Resets filter fields calling reset() method of each one</li>
     *     <li><code>clearHeaderFilters()</code>: Clears filter fields</li>
     *     <li><code>applyHeaderFilters()</code>: Applies filters values to Grid Store. The store will be also refreshed or reloaded if {@link #reloadOnChange} is true</li>
     * </ul>
     * 
     * # Enabled grid events
     * <ul>
     *     <li>{@link #headerfilterchange} : fired by Grid when some header filter changes value</li>
     *     <li>{@link #headerfiltersrender} : fired by Grid when header filters are rendered</li>
     *     <li>{@link #beforeheaderfiltersapply} : fired before filters are applied to Grid Store</li>
     *     <li>{@link #headerfiltersapply} : fired after filters are applied to Grid Store</li>
     * </ul>
     * 
     * @author Damiano Zucconi - http://www.isipc.it
     * @version 0.2.0
     */
    Ext.define('Ext.ux.grid.plugin.HeaderFilters',{
        
        ptype: 'gridheaderfilters',
        
        alternateClassName: ['Ext.ux.grid.HeaderFilters', 'Ext.ux.grid.header.Filters'],
        
        requires: [
            'Ext.container.Container',
            'Ext.tip.ToolTip'
        ],
    
    
    
    
        grid: null,
        
        fields: null,
        
        containers: null,
        
        storeLoaded: false,
        
        filterFieldCls: 'x-gridheaderfilters-filter-field',
        
        filterContainerCls: 'x-gridheaderfilters-filter-container',
        
        filterRoot: 'data',
        
        tooltipTpl: '{[Ext.isEmpty(values.filters) ? this.text.noFilter : "<b>"+this.text.activeFilters+"</b>"]}<br><tpl for="filters"><tpl if="value != \'\'">{[values.label ? values.label : values.property]} = {value}<br></tpl></tpl>',
        
        lastApplyFilters: null,
        
        bundle: {
            activeFilters: 'Active filters',
            noFilter: 'No filter'
        },
        
    	/**
    	* @cfg {Boolean} stateful
    	* Specifies if headerFilters values are saved into grid status when filters changes.
    	* This configuration can be overridden from grid configuration parameter <code>statefulHeaderFilters</code> (if defined).
    	* Used only if grid <b>is stateful</b>. Default = true.
    	* 
    	*/
    	stateful: true,
        
       /**
       * @cfg {Boolean} reloadOnChange
       * Specifies if the grid store will be auto-reloaded when filters change. The store
       * will be reloaded only if is was already loaded. If the store is local or it doesn't has remote filters
       * the store will be always updated on filters change.
       * 
       */
       reloadOnChange: true,
            
    	/**
       * @cfg {Boolean} ensureFilteredVisible
       * If the column on wich the filter is set is hidden and can be made visible, the
       * plugin makes the column visible.
       */
    	ensureFilteredVisible: true,
            
    	/**
    	* @cfg {Boolean} enableTooltip
    	* If a tooltip with active filters description must be enabled on the grid header
    	*/
    	enableTooltip: true,
    	
    	statusProperty: 'headerFilters',
    	
    	rendered: false,
        
       constructor: function(cfg) 
       {
           if(cfg)
           {
           	Ext.apply(this,cfg);
           }
       },
        
       init: function(grid)
       {
    	   this.grid = grid;
            
            /*var storeProxy = this.grid.getStore().getProxy();
            if(storeProxy && storeProxy.getReader())
            {
                var reader = storeProxy.getReader();
                this.filterRoot = reader.root ? reader.root : undefined;
            }*/
            /**
             * @cfg {Object} headerFilters
             * <b>Configuration attribute for grid</b>
             * Allows to initialize header filters values from grid configuration.
             * This object must have filter names as keys and filter values as values.
             * If this plugin has {@link #stateful} enabled, the saved filters have priority and override these filters.
             * Use {@link #ignoreSavedHeaderFilters} to ignore current status and apply these filters directly.
             */
    	   if(!grid.headerFilters)
    		   grid.headerFilters = {};
            
            
    	   if(Ext.isBoolean(grid.statefulHeaderFilters))
           {
    		   this.setStateful(grid.statefulHeaderFilters);
           }
            
    		this.grid.addEvents(
          /**
            * @event headerfilterchange
            * <b>Event enabled on the Grid</b>: fired when at least one filter is updated after apply.
            * @param {Ext.grid.Panel} grid The grid
            * @param {Ext.util.MixedCollection} filters The applied filters (after apply). Ext.util.Filter objects.
            * @param {Ext.util.MixedCollection} prevFilters The old applied filters (before apply). Ext.util.Filter objects.
            * @param {Number} active Number of active filters (not empty)
            * @param {Ext.data.Store} store Current grid store
            */    
            'headerfilterchange',
            /**
             * @event headerfiltersrender
             * <b>Event enabled on the Grid</b>: fired when filters are rendered
             * @param {Ext.grid.Panel} grid The grid
             * @param {Object} fields The filter fields rendered. The object has for keys the filters names and for value Ext.form.field.Field objects.
             * @param {Object} filters Current header filters. The object has for keys the filters names and for value the filters values.
            */
    			'headerfiltersrender',
            	/**
             * @event beforeheaderfiltersapply
             * <b>Event enabled on the Grid</b>: fired before filters are confirmed. If the handler returns false no filter apply occurs.
             * @param {Ext.grid.Panel} grid The grid
             * @param {Object} filters Current header filters. The object has for keys the filters names and for value the filters values.
             * @param {Ext.data.Store} store Current grid store
             */
            'beforeheaderfiltersapply',
            /**
             * @event headerfiltersapply
             *<b>Event enabled on the Grid</b>: fired when filters are confirmed.
             * @param {Ext.grid.Panel} grid The grid
             * @param {Object} filters Current header filters. The object has for keys the filters names and for value the filters values.
             * @param {Number} active Number of active filters (not empty)
             * @param {Ext.data.Store} store Current grid store
             */
            'headerfiltersapply'
            );
            
            this.grid.on({
            	scope: this,
                columnresize: this.resizeFilterContainer,
                beforedestroy: this.onDestroy,
                beforestatesave: this.saveFilters,
                afterlayout: this.adjustFilterWidth
            });
            
            this.grid.headerCt.on({
                scope: this,
                afterrender: this.renderFilters
            });
            
            this.grid.getStore().on({
                scope: this,
                load: this.onStoreLoad
            });
            
            if(this.reloadOnChange)
            {
                this.grid.on('headerfilterchange',this.reloadStore, this);
            }
            
            if(this.stateful)
            {
                this.grid.addStateEvents('headerfilterchange');
            }
            
            //Enable new grid methods
            Ext.apply(this.grid, 
            {
                headerFilterPlugin: this,
                setHeaderFilter: function(sName, sValue)
                {
                    if(!this.headerFilterPlugin)
                        return;
                    var fd = {};
                    fd[sName] = sValue;
                    this.headerFilterPlugin.setFilters(fd);
                },
                /**
                 * Returns a collection of filters corresponding to enabled header filters.
                 * If a filter field is disabled, the filter is not included.
                 * <b>This method is enabled on Grid</b>.
                 * @method
                 * @return {Array[Ext.util.Filter]} An array of Ext.util.Filter
                 */
                getHeaderFilters: function()
                {
                    if(!this.headerFilterPlugin)
                        return null;
                    return this.headerFilterPlugin.getFilters();
                },
                /**
                 * Set header filter values
                 * <b>Method enabled on Grid</b>
                 * @method
                 * @param {Object or Array[Object]} filters An object with key/value pairs or an array of Ext.util.Filter objects (or corresponding configuration).
                 * Only filters that matches with header filters names will be set
                 */
                setHeaderFilters: function(obj)
                {
                    if(!this.headerFilterPlugin)
                        return;
                    this.headerFilterPlugin.setFilters(obj);
                },
                getHeaderFilterField: function(fn)
                {
                    if(!this.headerFilterPlugin)
                        return;
                    if(this.headerFilterPlugin.fields[fn])
                        return this.headerFilterPlugin.fields[fn];
                    else
                        return null;
                },
                resetHeaderFilters: function()
                {
                    if(!this.headerFilterPlugin)
                        return;
                    this.headerFilterPlugin.resetFilters();
                },
                clearHeaderFilters: function()
                {
                    if(!this.headerFilterPlugin)
                        return;
                    this.headerFilterPlugin.clearFilters();
                },
                applyHeaderFilters: function()
                {
                    if(!this.headerFilterPlugin)
                        return;
                    this.headerFilterPlugin.applyFilters();
                }
            });
       },
        
       
        
    	saveFilters: function(grid, status)
    	{
    		status[this.statusProperty] = (this.stateful && this.rendered) ? this.parseFilters() : grid[this.statusProperty];
    	},
        
        setFieldValue: function(field, value)
        {
        	var column = field.column;
            if(!Ext.isEmpty(value))
            {
                field.setValue(value);
                if(!Ext.isEmpty(value) && column.hideable && !column.isVisible() && !field.isDisabled() && this.ensureFilteredVisible)
                {
                	column.setVisible(true);
                }
            }
            else
            {
            	field.setValue('');
            }
        },
        
        renderFilters: function()
        {
            this.destroyFilters();
            
            this.fields = {};
            this.containers = {};
    
    
    
    
            var filters = this.grid.headerFilters;
            
            /**
             * @cfg {Boolean} ignoreSavedHeaderFilters
             * <b>Configuration parameter for grid</b>
             * Allows to ignore saved filter status when {@link #stateful} is enabled.
             * This can be useful to use {@link #headerFilters} configuration directly and ignore status.
             * The state will still be saved if {@link #stateful} is enabled.
             */
            if(this.stateful && this.grid[this.statusProperty] && !this.grid.ignoreSavedHeaderFilters)
            {
                Ext.apply(filters, this.grid[this.statusProperty]);
            }
            
            var storeFilters = this.parseStoreFilters();
            filters = Ext.apply(storeFilters, filters);
            
            var columns = this.grid.headerCt.getGridColumns(true);
            for(var c=0; c < columns.length; c++)
            {
                var column = columns[c];
                if(column.filter)
                {
                    var filterContainerConfig = {
                        itemId: column.id + '-filtersContainer',
                        cls: this.filterContainerCls,
                        layout: 'anchor',
                        bodyStyle: {'background-color': 'transparent'},
                        border: false,
                        width: column.getWidth(),
                        listeners: {
                            scope: this,
                            element: 'el',
                            mousedown: function(e)
                            {
                                e.stopPropagation();
                            },
                            click: function(e)
                            {
                                e.stopPropagation();
                            },
                            keydown: function(e){
                                 e.stopPropagation();
                            },
                            keypress: function(e){
                                 e.stopPropagation();
                                 if(e.getKey() == Ext.EventObject.ENTER)
                                 {
                                     this.onFilterContainerEnter();
                                 }
                            },
                            keyup: function(e){
                                 e.stopPropagation();
                            }
                        },
                        items: []
                    }
                    
                    var fca = [].concat(column.filter);
                        
                    for(var ci = 0; ci < fca.length; ci++)
                    {
                        var fc = fca[ci];
                        Ext.applyIf(fc, {
                            filterName: column.dataIndex,
                            fieldLabel: column.text || column.header,
                            hideLabel: fca.length == 1
                        });
                        var initValue = Ext.isEmpty(filters[fc.filterName]) ? null : filters[fc.filterName];
                        Ext.apply(fc, {
                            cls: this.filterFieldCls,
                            itemId: fc.filterName,
                            anchor: '-1'
                        });
                        var filterField = Ext.ComponentManager.create(fc);
                        filterField.column = column;
                        this.setFieldValue(filterField, initValue);
                        this.fields[filterField.filterName] = filterField;
                        filterContainerConfig.items.push(filterField);
                    }
                    
                    var filterContainer = Ext.create('Ext.container.Container', filterContainerConfig);
                    filterContainer.render(column.el);
                    this.containers[column.id] = filterContainer;
                    column.setPadding = Ext.Function.createInterceptor(column.setPadding, function(h){return false});
                }
            }
            
            if(this.enableTooltip)
            {
                this.tooltipTpl = new Ext.XTemplate(this.tooltipTpl,{text: this.bundle});
                this.tooltip = Ext.create('Ext.tip.ToolTip',{
                    target: this.grid.headerCt.el,
                    //delegate: '.'+this.filterContainerCls,
                    renderTo: Ext.getBody(),
                    html: this.tooltipTpl.apply({filters: []})
                });        
                this.grid.on('headerfilterchange',function(grid, filters)
                {
                    var sf = filters.filterBy(function(filt){
                        return !Ext.isEmpty(filt.value);
                    });
                    this.tooltip.update(this.tooltipTpl.apply({filters: sf.getRange()}));
                },this);
            }
            
            this.applyFilters();
            this.rendered = true;
            this.grid.fireEvent('headerfiltersrender',this.grid,this.fields,this.parseFilters());
        },
        
        onStoreLoad: function()
        {
            this.storeLoaded = true;
        },
        
        onFilterContainerEnter: function()
        {
            this.applyFilters();
        },
        
        resizeFilterContainer: function(headerCt,column,w,opts)
        {
             if(!this.containers)             return;
            var cnt = this.containers[column.id];
            if(cnt)
            {
                cnt.setWidth(w);
                cnt.doLayout();
            }
        },
        
        destroyFilters: function()
        {
        	this.rendered = false;
    	     if(this.fields)
    	     {
    	         for(var f in this.fields)
    	             Ext.destroy(this.fields[f]);
    	         delete this.fields;
    	     }
    	 
    	     if(this.containers)
    	     {
    	         for(var c in this.containers)
    	             Ext.destroy(this.containers[c]);
    	         delete this.containers;
    	     }
        },
        
        onDestroy: function()
        {
            this.destroyFilters();
            Ext.destroy(this.tooltip, this.tooltipTpl);
        },
        
    	 adjustFilterWidth: function() 
        {
        	if(!this.containers) return;
    		var columns = this.grid.headerCt.getGridColumns(true);        
    		for(var c=0; c < columns.length; c++) 
    		{           
    			var column = columns[c];            
    			if (column.filter && column.flex) 
    			{               
    				this.containers[column.id].setWidth(column.getWidth()-1);            
    			}
    	  	}
    	 },
       
        resetFilters: function()
        {
            if(!this.fields)
                return;
            for(var fn in this.fields)
            {
                var f = this.fields[fn];
                if(!f.isDisabled() && !f.readOnly && Ext.isFunction(f.reset))
                    f.reset();
            }
            this.applyFilters();
        },
        
        clearFilters: function()
        {
            if(!this.fields)
                return;
            for(var fn in this.fields)
            {
                var f = this.fields[fn];
                if(!f.isDisabled() && !f.readOnly)
                    f.setValue('');
            }
            this.applyFilters();
        },
        
        setFilters: function(filters)
        {
            if(!filters)
                return;
            
            if(Ext.isArray(filters))
            {
                var conv = {};
                Ext.each(filters, function(filter){
                    if(filter.property)
                    {
                        conv[filter.property] = filter.value; 
                    }
                });
                filters = conv;
            }
            else if(!Ext.isObject(filters))
            {
                return;
            }
    
    
    
    
            this.initFilterFields(filters);
            this.applyFilters();
        },
        
        getFilters: function()
        {
            var filters = this.parseFilters();
            var res = new Ext.util.MixedCollection();
            for(var fn in filters)
            {
                var value = filters[fn];
                var field = this.fields[fn];
                res.add(new Ext.util.Filter({
                    property: fn,
                    value: value,
                    root: this.filterRoot,
                    label: field.fieldLabel
                }));
            }
            return res;
        },
        
        parseFilters: function()
        {
            var filters = {};
            if(!this.fields)
                return filters;
            for(var fn in this.fields)
            {
                var field = this.fields[fn];
                if(!field.isDisabled() && field.isValid())
                    filters[field.filterName] = field.getSubmitValue();
            }
            return filters;
        },
        
        initFilterFields: function(filters)
        {
            if(!this.fields)
                return;
    
    
    
    
            for(var fn in  filters)
            {
                var value = filters[fn];
                var field = this.fields[fn];
                if(field)
                {
                    this.setFieldValue(filterField, initValue);
                }
            }
        },
        
        countActiveFilters: function()
        {
            var fv = this.parseFilters();
            var af = 0;
            for(var fn in fv)
            {
                if(!Ext.isEmpty(fv[fn]))
                    af ++;
            }
            return af;
        },
        
        parseStoreFilters: function()
        {
            var sf = this.grid.getStore().filters;
            var res = {};
            sf.each(function(filter){
                var name = filter.property;
                var value = filter.value;
                if(name && value)
                {
                    res[name] = value;            
                }
            });
            return res;
        },
        
        applyFilters: function()
        {
            var filters = this.parseFilters();
            if(this.grid.fireEvent('beforeheaderfiltersapply', this.grid, filters, this.grid.getStore()) !== false)
            {
                var storeFilters = this.grid.getStore().filters;
                var exFilters = storeFilters.clone();
                var change = false;
                var active = 0;
                for(var fn in filters)
                {
                    var value = filters[fn];
                    
                    var sf = storeFilters.findBy(function(filter){
                        return filter.property == fn;
                    });
                    
                    if(Ext.isEmpty(value))
                    {
                        if(sf)
                        {
                            storeFilters.remove(sf);
                            change = true;
                        }
                    }
                    else
                    {
                        var field = this.fields[fn];
                        if(!sf || sf.value != filters[fn])
                        {
                            var newSf = new Ext.util.Filter({
                                root: this.filterRoot,
                                property: fn,
                                value: filters[fn],
                                label: field.fieldLabel
                            });
                            if(sf)
                            {
                                storeFilters.remove(sf);
                            }
                            storeFilters.add(newSf);
                            change = true;
                        }
                        active ++;
                    }
                }
                
                this.grid.fireEvent('headerfiltersapply', this.grid, filters, active, this.grid.getStore());
                if(change)
                {
                    var curFilters = this.getFilters();
                    this.grid.fireEvent('headerfilterchange', this.grid, curFilters, this.lastApplyFilters, active, this.grid.getStore());
                    this.lastApplyFilters = curFilters;
                }
            }
        },
        
    	reloadStore: function()
    	{
    		var gs = this.grid.getStore();
    		if(this.grid.getStore().remoteFilter)
    		{
    			if(this.storeLoaded)
    			{
    				gs.currentPage = 1;
    				gs.load();
    			}
    		}
    		else
          {
    			if(gs.filters.getCount()) 
             {
    				if(!gs.snapshot)
    					gs.snapshot = gs.data.clone();
    				else
    				{
    					gs.currentPage = 1;
    				}
                gs.data = gs.snapshot.filter(gs.filters.getRange());
                var doLocalSort = gs.sortOnFilter && !gs.remoteSort;
                if(doLocalSort)
    				{
    					gs.sort();
    				}
                // fire datachanged event if it hasn't already been fired by doSort
                if (!doLocalSort || gs.sorters.length < 1) 
                {
                	gs.fireEvent('datachanged', gs);
    				}
    			}
    		   else
    		   {
    				if(gs.snapshot)
    				{
    					gs.currentPage = 1;
    					gs.data = gs.snapshot.clone();
    		         delete gs.snapshot;
    		         gs.fireEvent('datachanged', gs);
    				}
    			}
    		}
    	}
    });

    Last edited by d.zucconi; 4 Mar 2012 at 11:25 PM. Reason: Updated source code for version 0.2.0

  2. #2
    Sencha User
    Join Date
    Oct 2011
    Posts
    1
    Vote Rating
    0
    asani is on a distinguished road

      0  

    Default


    I have problem with this plugin, all time have error in gridplugin.js:453

    PHP Code:
    Uncaught TypeErrorCannot read property 'gridcolumn-1051' of null 

  3. #3
    Sencha User
    Join Date
    Oct 2011
    Posts
    1
    Vote Rating
    1
    bsot is on a distinguished road

      1  

    Default


    I had the same problem. You can add a check before using this.containers in resizeFilterContainer :

    Code:
        resizeFilterContainer: function (headerCt, column, w, opts) {
            if (!this.containers)
                return;
            var cnt = this.containers[column.id];
            if (cnt) {
                cnt.setWidth(w);
                cnt.doLayout();
            }
        },

  4. #4
    Sencha Premium Member d.zucconi's Avatar
    Join Date
    Jun 2008
    Location
    Piacenza (Italy)
    Posts
    78
    Vote Rating
    5
    d.zucconi is on a distinguished road

      0  

    Default


    Quote Originally Posted by bsot View Post
    I had the same problem. You can add a check before using this.containers in resizeFilterContainer :

    Code:
        resizeFilterContainer: function (headerCt, column, w, opts) {
            if (!this.containers)
                return;
            var cnt = this.containers[column.id];
            if (cnt) {
                cnt.setWidth(w);
                cnt.doLayout();
            }
        },
    Thanks. Code updated on first post of this thread.

  5. #5
    Sencha User
    Join Date
    Jul 2011
    Posts
    1
    Vote Rating
    0
    Arjuna75 is on a distinguished road

      0  

    Default


    Very good plugin!

    Thank you

  6. #6
    Sencha User krish.sadasivam's Avatar
    Join Date
    Oct 2011
    Location
    Jersey City, NJ
    Posts
    5
    Vote Rating
    0
    krish.sadasivam is on a distinguished road

      0  

    Default


    Thanks a lot d.zucconi..

  7. #7
    Sencha User
    Join Date
    Sep 2011
    Posts
    1
    Vote Rating
    0
    zaggi is on a distinguished road

      0  

    Default Bad filter sizing

    Bad filter sizing


    When you set column with flex property, filter input after render has default width (100).

    My proposal is:

    add function to grid afterlayout event

    PHP Code:
    afterlayoutthis.adjustFilterWidth 
    PHP Code:
    adjustFilterWidth: function() {        
      var 
    columns this.grid.headerCt.getGridColumns(true);        
      for(var 
    c=0columns.lengthc++) {           
         var 
    column columns[c];            
              if (
    column.filter && column.flex) {               
                   
    this.containers[column.id].setWidth(column.getWidth()-1);            
              }        
      }    

    This is effective solution. Width -1 <- is nicer

  8. #8
    Ext JS Premium Member Spenna's Avatar
    Join Date
    Apr 2008
    Posts
    56
    Vote Rating
    0
    Spenna is on a distinguished road

      0  

    Default


    Can't get this to work, could you provide a working sample?

  9. #9
    Sencha Premium Member d.zucconi's Avatar
    Join Date
    Jun 2008
    Location
    Piacenza (Italy)
    Posts
    78
    Vote Rating
    5
    d.zucconi is on a distinguished road

      0  

    Default


    Quote Originally Posted by zaggi View Post
    When you set column with flex property, filter input after render has default width (100).

    My proposal is:

    add function to grid afterlayout event

    PHP Code:
    afterlayoutthis.adjustFilterWidth 
    ...
    Thanks for your suggestion, code updated on the first post of this thread.

  10. #10
    Sencha User
    Join Date
    Sep 2011
    Posts
    4
    Vote Rating
    0
    swisssphere is on a distinguished road

      0  

    Default Problem with infinit-scroll using the filterbar

    Problem with infinit-scroll using the filterbar


    Bongiorno d.zucconi

    Grazie per la tua lavora. Thank you for your work. I'm a newcomer working with extjs.

    I made some tries with a grid using an infinite-slider function for reloading data from a MySql-table with many records.
    I used the examle "infinite-scroll" and added your class and other stuff. I use external sort and filter.
    A lot is working fine. You can see it on http://holzundsonne.ch/extdemo1.

    The Problem now is: If you set the filter at the addresscoloumn to "94", you get 450 records back. The first 200 where loaded and 20 of them are displayed correct. But size of the "scrollbuttom" insn't resized to 450 records, it has still the size for the unfiltered 9000 records. Second, when I scroll down, there are multiple times the rownumbers between 1 to 450.

    Do you have a hint, how I can fix that?
    Many thanks and Saluti Cordiale


    Programmcode:
    grid_js.txt


    29.11.2011:
    Hello d.zucconi
    I still have this problem with the resize of the scrollbutton and displaying multiple time the data-records at the grid. Here is an example, see
    http://holzundsonne.ch/extdemo1:

    - no filter applied: result 8995 record, scrollbarbutton is small, scrolling is OK
    - filter for column address=19: result 423 records, scrollbarbutton isn't resized, scrolling is not correct
    - filter for column address=197: result 27 records, scrollbarbutton isn't resized, scrolling is not correct
    - filter for column address=1970: result 9 records, no scrollbar is nessesary, OK

    Please help me, how I can refresh the size of scrollbarbutton correct.
    Best regards and many thanks.

    30.11.2011 I've founded a solution:
    The "infinite-scroll" example uses a property called

    invalidateScrollerOnRefresh: falsethis disabled the resizing of the scrollbar. My solution is now to allow the resizing of the scrollbar in "applyFilters":

    ...
    this.grid.fireEvent('headerfiltersapply', this.grid, filters, active, this.grid.getStore());

    if(change)
    {
    var curFilters = this.getFilters();
    this.grid.fireEvent('headerfilterchange', this.grid, curFilters, this.lastApplyFilters, active, this.grid.getStore());
    this.lastApplyFilters = curFilters;
    this.grid.invalidateScrollerOnRefresh= true;
    }
    ...

    Greetings

    Last edited by swisssphere; 30 Nov 2011 at 3:58 AM. Reason: found a solution