PDA

View Full Version : Ext.ux.grid.FilterBar plugin



ldonofrio
31 Oct 2011, 10:41 AM
v1.1 on Sencha Market. Supports operators for number and date filters
https://market.sencha.com/users/68/addons/95 (http://market.sencha.com/users/68/addons/95)


UPDATED CODE FOR 4.1 (2012-06-01):


/**
* Plugin that enable filters on the grid header.<br>
* The header filters are integrated with new Ext4 <code>Ext.data.Store</code> filters.<br>
*
* @author Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* @version 1.0 beta 1 (supports 4.1 beta)
* @updated 2011-10-18 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Support renderHidden config option, isVisible(), and setVisible() methods (added getFilterBar() method to the grid)
* Fix filter bug that append filters to Store filters MixedCollection
* Fix layout broken on initial render when columns have width property
* @updated 2011-10-24 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Rendering code rewrited, filters are now rendered inside de column headers, this solves scrollable grids issues, now scroll, columnMove, and columnHide/Show is handled by the headerCt
* Support showClearButton config option, render a clear Button for each filter to clear the applied filter (uses Ext.ux.form.field.ClearButton plugin)
* Added clearFilters() method.
* @updated 2011-10-25 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Allow preconfigured filter's types and auto based on store field data types
* Auto generated stores for combo and list filters (local collect or server in autoStoresRemoteProperty response property)
* @updated 2011-10-26 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Completelly rewriten to support reconfigure filters on grid's reconfigure
* Supports clearAll and showHide buttons rendered in an actioncolumn or in new generetad small column
* @updated 2011-10-27 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Added support to 4.0.7 (columnresize not fired correctly on this build)
* @updated 2011-11-02 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Filter on ENTER
* Defaults submitFormat on date filter to 'Y-m-d' and use that in applyFilters for local filtering
* Added null value support on combo and list filters (autoStoresNullValue and autoStoresNullText)
* Fixed some combo styles
* @updated 2011-11-10 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Parse and show initial filters applied to the store (only property -> value filters, filterFn is unsuported)
* @updated 2011-12-12 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Extends AbstractPlugin and use Observable as a Mixin
* Yes/No localization on constructor
* @updated 2012-01-03 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Added some support for 4.1 beta
* @updated 2012-01-05 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* 99% support for 4.1 beta. Seems to be working
* @updated 2012-03-22 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Fix focusFirstField method
* Allow to specify listConfig in combo filter
* Intercept column's setPadding for all columns except actionColumn or extraColumn (fix checkBoxSelectionModel header)
* @updated 2012-05-07 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Fully tested on 4.1 final
* @updated 2012-05-31 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Fix padding issue on checkbox column
*/

Ext.define('Ext.ux.grid.FilterBar', {
extend: 'Ext.AbstractPlugin',
alias: 'plugin.filterbar',
uses: [
'Ext.window.MessageBox',
'Ext.ux.form.field.ClearButton',
'Ext.container.Container',
'Ext.util.DelayedTask',
'Ext.layout.container.HBox',
'Ext.data.ArrayStore',
'Ext.button.Button',
'Ext.form.field.Text',
'Ext.form.field.Number',
'Ext.form.field.Date',
'Ext.form.field.ComboBox'
],
mixins: {
observable: 'Ext.util.Observable'
},

updateBuffer : 800, // buffer time to apply filtering when typing/selecting

columnFilteredCls : Ext.baseCSSPrefix + 'column-filtered', // CSS class to apply to the filtered column header

renderHidden : true, // renders the filters hidden by default, use in combination with showShowHideButton
showShowHideButton : true, // add show/hide button in actioncolumn header if found, if not a new small column is created
showHideButtonTooltipDo : 'Show filter bar', // button tooltip show
showHideButtonTooltipUndo : 'Hide filter bar', // button tooltip hide
showHideButtonIconCls : 'filter', // button iconCls

showClearButton : true, // use Ext.ux.form.field.ClearButton to allow user to clear each filter, the same as showShowHideButton
showClearAllButton : true, // add clearAll button in actioncolumn header if found, if not a new small column is created
clearAllButtonIconCls : 'clear-filters', // css class with the icon of the clear all button
clearAllButtonTooltip : 'Clear all filters', // button tooltip

autoStoresRemoteProperty : 'autoStores', // if no store is configured for a combo filter then stores are created automatically, if remoteFilter is true then use this property to return arrayStores from the server
autoStoresNullValue : '###NULL###', // value send to the server to expecify null filter
autoStoresNullText : '[empty]', // NULL Display Text
autoUpdateAutoStores : false, // if set to true combo autoStores are updated each time that a filter is applied

boolTpl: {
xtype: 'combo',
queryMode: 'local',
forceSelection: true,
triggerAction: 'all',
editable: false,
store: [
[1, 'Yes'],
[0, 'No']
],
operator: 'eq'
},
dateTpl: {
xtype: 'datefield',
editable: true,
submitFormat: 'Y-m-d',
operator: 'eq'
},
floatTpl: {
xtype: 'numberfield',
allowDecimals: true,
minValue: 0,
hideTrigger: true,
keyNavEnabled: false,
mouseWheelEnabled: false,
operator: 'eq'
},
intTpl: {
xtype: 'numberfield',
allowDecimals: false,
minValue: 0,
operator: 'eq'
},
stringTpl: {
xtype: 'textfield',
operator: 'like'
},
comboTpl: {
xtype: 'combo',
queryMode: 'local',
forceSelection: true,
editable: false,
triggerAction: 'all',
operator: 'eq'
},
listTpl: {
xtype: 'combo',
queryMode: 'local',
forceSelection: true,
editable: false,
triggerAction: 'all',
multiSelect: true,
operator: 'in'
},

constructor: function() {
var me = this;

me.boolTpl.store[0][1] = Ext.htmlDecode(Ext.MessageBox.buttonText.yes);
me.boolTpl.store[1][1] = Ext.htmlDecode(Ext.MessageBox.buttonText.no);

me.mixins.observable.constructor.call(me);
me.callParent(arguments);
},

// private
init: function(grid) {
var me = this;

grid.on({
columnresize: me.resizeContainer,
columnhide: me.resizeContainer,
columnshow: me.resizeContainer,
beforedestroy: me.unsetup,
reconfigure: me.resetup,
scope: me
});

grid.addEvents('filterupdated');

Ext.apply(grid, {
filterBar: me,
getFilterBar: function() {
return this.filterBar;
}
});

me.setup(grid);
},

// private
setup: function(grid) {
var me = this;

me.grid = grid;
me.visible = !me.renderHidden;
me.autoStores = Ext.create('Ext.util.MixedCollection');
me.autoStoresLoaded = false;
me.columns = Ext.create('Ext.util.MixedCollection');
me.containers = Ext.create('Ext.util.MixedCollection');
me.fields = Ext.create('Ext.util.MixedCollection');
me.actionColumn = me.grid.down('actioncolumn') || me.grid.down('actioncolumnpro');
me.extraColumn = null;
me.clearAllEl = null;
me.showHideEl = null;
me.task = Ext.create('Ext.util.DelayedTask');
me.filterArray = [];

me.overrideProxy();
me.parseFiltersConfig(); // sets me.columns and me.autoStores
me.parseInitialFilters(); // sets me.filterArray with the store previous filters if any (adds operator and type if missing)
me.renderExtraColumn(); // sets me.extraColumn if applicable

// renders the filter's bar
if (grid.rendered) {
me.renderFilterBar(grid);
} else {
grid.on('afterrender', me.renderFilterBar, me, { single: true });
}
},

// private
unsetup: function(grid) {
var me = this;

if (me.autoStores.getCount()) {
me.grid.store.un('load', me.fillAutoStores, me);
}

me.autoStores.each(function(item) {
Ext.destroy(item);
});
me.autoStores.clear();
me.autoStores = null;
me.columns.each(function(column) {
if (column.rendered) {
if(column.getEl().hasCls(me.columnFilteredCls)) {
column.getEl().removeCls(me.columnFilteredCls);
}
}
}, me);
me.columns.clear();
me.columns = null;
me.fields.each(function(item) {
Ext.destroy(item);
});
me.fields.clear();
me.fields = null;
me.containers.each(function(item) {
Ext.destroy(item);
});
me.containers.clear();
me.containers = null;
if (me.clearAllEl) {
Ext.destroy(me.clearAllEl);
me.clearAllEl = null;
}
if (me.showHideEl) {
Ext.destroy(me.showHideEl);
me.showHideEl = null;
}
if (me.extraColumn) {
me.grid.headerCt.items.remove(me.extraColumn);
Ext.destroy(me.extraColumn);
me.extraColumn = null;
}
me.task = null;
me.filterArray = null;
},

// private
resetup: function(grid) {
var me = this;

me.unsetup(grid);
me.setup(grid);
},

// private
overrideProxy: function() {
var me = this;

// override encodeFilters to append type and operator in remote filtering
Ext.apply(me.grid.store.proxy, {
encodeFilters: function(filters) {
var min = [],
length = filters.length,
i = 0;

for (; i < length; i++) {
min[i] = {
property: filters[i].property,
value : filters[i].value
};
if (filters[i].type) {
min[i].type = filters[i].type;
}
if (filters[i].operator) {
min[i].operator = filters[i].operator;
}
}
return this.applyEncoding(min);
}
});
},

// private
parseFiltersConfig: function() {
var me = this;
var columns = this.grid.headerCt.getGridColumns(true);
me.columns.clear();
me.autoStores.clear();
Ext.each(columns, function(column) {
if (column.filter) {
if (column.filter === true || column.filter === 'auto') { // automatic types configuration (store based)
var type = me.grid.store.model.prototype.fields.get(column.dataIndex).type.type;
if (type == 'auto') type = 'string';
column.filter = type;
}
if (Ext.isString(column.filter)) {
column.filter = {
type: column.filter // only set type to then use templates
};
}
if (column.filter.type) {
column.filter = Ext.applyIf(column.filter, me[column.filter.type + 'Tpl']); // also use templates but with user configuration
}

if (column.filter.xtype == 'combo' && !column.filter.store) {
column.autoStore = true;
column.filter.store = Ext.create('Ext.data.ArrayStore', {
fields: [{
name: 'text'
},{
name: 'id'
}]
});
me.autoStores.add(column.dataIndex, column.filter.store);
column.filter = Ext.apply(column.filter, {
displayField: 'text',
valueField: 'id'
});
}

if (!column.filter.type) {
switch(column.filter.xtype) {
case 'combo':
column.filter.type = (column.filter.multiSelect ? 'list' : 'combo');
break;
case 'datefield':
column.filter.type = 'date';
break;
case 'numberfield':
column.filter.type = (column.filter.allowDecimals ? 'float' : 'int');
break;
default:
column.filter.type = 'string'
}
}

if (!column.filter.operator) {
column.filter.operator = me[column.filter.type + 'Tpl'].operator;
}
me.columns.add(column.dataIndex, column);
}
}, me);
if (me.autoStores.getCount()) {
if (me.grid.store.getCount() > 0) {
me.fillAutoStores(me.grid.store);
}
if (me.grid.store.remoteFilter) {
var autoStores = [];
me.autoStores.eachKey(function(key, item) {
autoStores.push(key);
});
me.grid.store.proxy.extraParams = me.grid.store.proxy.extraParams || {};
me.grid.store.proxy.extraParams[me.autoStoresRemoteProperty] = autoStores;
}
me.grid.store.on('load', me.fillAutoStores, me);
}
},

// private
fillAutoStores: function(store) {
var me = this;

if (!me.autoUpdateAutoStores && me.autoStoresLoaded) return;

me.autoStores.eachKey(function(key, item) {
var field = me.fields.get(key);
if (field) {
field.suspendEvents();
var fieldValue = field.getValue();
}
if (!store.remoteFilter) { // values from local store
var data = store.collect(key, true, false).sort();
var records = [];
Ext.each(data, function(txt) {
if (Ext.isEmpty(txt)) {
Ext.Array.insert(records, 0, [{
text: me.autoStoresNullText,
id: me.autoStoresNullValue
}]);
} else {
records.push({
text: txt,
id: txt
});
}
});
item.loadData(records);
} else { // values from server
if (store.proxy.reader.rawData[me.autoStoresRemoteProperty]) {
var data = store.proxy.reader.rawData[me.autoStoresRemoteProperty];
if (data[key]) {
var records = [];
Ext.each(data[key].sort(), function(txt) {
if (Ext.isEmpty(txt)) {
Ext.Array.insert(records, 0, [{
text: me.autoStoresNullText,
id: me.autoStoresNullValue
}]);
} else {
records.push({
text: txt,
id: txt
});
}
});
item.loadData(records);
}
}
}
if (field) {
field.setValue(fieldValue);
field.resumeEvents();
}
}, me);
me.autoStoresLoaded = true;
if (me.grid.store.remoteFilter && !me.autoUpdateAutoStores) {
delete me.grid.store.proxy.extraParams[me.autoStoresRemoteProperty];
}
},

// private
parseInitialFilters: function() {
var me = this;

me.filterArray = [];
me.grid.store.filters.each(function(filter) {
// try to parse initial filters, for now filterFn is unsuported
if (filter.property && !Ext.isEmpty(filter.value) && me.columns.get(filter.property)) {
if (!filter.type) filter.type = me.columns.get(filter.property).filter.type;
if (!filter.operator) filter.operator = me.columns.get(filter.property).filter.operator;
me.filterArray.push(filter);
}
}, me);
},

// private
renderExtraColumn: function() {
var me = this;

if (me.columns.getCount() && !me.actionColumn && (me.showClearAllButton || me.showShowHideButton)) {
var extraColumnCssClass = Ext.baseCSSPrefix + 'filter-bar-extra-column-hack';
if (!document.getElementById(extraColumnCssClass)) {
var style = document.createElement('style');
var css = 'tr.' + Ext.baseCSSPrefix + 'grid-row td.' + extraColumnCssClass + ' { background-color: #ffffff !important; border-color: #ffffff !important; }';
style.setAttribute('type', 'text/css');
style.setAttribute('id', extraColumnCssClass);
document.body.appendChild(style);
if (style.styleSheet) { // IE
style.styleSheet.cssText = css;
} else { // others
var cssNode = document.createTextNode(css);
style.appendChild(cssNode);
}
}
me.extraColumn = Ext.create('Ext.grid.column.Column', {
draggable: false,
hideable: false,
menuDisabled: true,
sortable: false,
resizable: false,
fixed: true,
width: 28,
minWidth: 28,
maxWidth: 28,
header: '&nbsp;',
tdCls: extraColumnCssClass
});
me.grid.headerCt.add(me.extraColumn);
}
},

// private
renderFilterBar: function(grid) {
var me = this;

me.containers.clear();
me.fields.clear();
me.columns.eachKey(function(key, column) {
var listConfig = column.filter.listConfig || {};
listConfig = Ext.apply(listConfig, {
style: 'border-top-width: 1px'
});
var field = Ext.widget(column.filter.xtype, Ext.apply(column.filter, {
dataIndex: key,
flex: 1,
margin: 0,
fieldStyle: 'border-left-width: 0px; border-bottom-width: 0px;',
listConfig: listConfig,
preventMark: true,
enableKeyEvents: true,
listeners: {
change: me.applyFilters,
keypress: function(txt, e){
if(e.getCharCode() == 13) {
me.applyFilters(txt, txt.getValue());
e.stopEvent();
}
},
scope: me
},
plugins: (!me.showClearButton ? [] : [{
ptype: 'clearbutton'
}])
}));
me.fields.add(column.dataIndex, field);
var container = Ext.create('Ext.container.Container', {
dataIndex: key,
layout: 'hbox',
bodyStyle: 'background-color: "transparent";',
width: column.getWidth(),
items: [field],
listeners: {
scope: me,
element: 'el',
mousedown: function(e) { e.stopPropagation(); },
click: function(e) { e.stopPropagation(); },
dblclick: function(e) { e.stopPropagation(); }/*,
keydown: function(e) { e.stopPropagation(); },
keypress: function(e) { e.stopPropagation(); },
keyup: function(e) { e.stopPropagation(); }*/
}
});
me.containers.add(column.dataIndex, container);
container.render(Ext.get(column.id));
}, me);
var excludedCols = [];
if (me.actionColumn) excludedCols.push(me.actionColumn.id);
if (me.extraColumn) excludedCols.push(me.extraColumn.id);
Ext.each(me.grid.headerCt.getGridColumns(true), function(column) {
if (!Ext.Array.contains(excludedCols, column.id)) {
column.setPadding = Ext.Function.createInterceptor(column.setPadding, function(h) {
if (column.text == ' ') { //checkbox column
this.titleEl.setStyle({
paddingTop: '4px'
});
}
return false;
});
}
});


me.setVisible(me.visible);

me.renderButtons();

me.showInitialFilters();
},

//private
renderButtons: function() {
var me = this;

if (me.showShowHideButton && me.columns.getCount()) {
var column = me.actionColumn || me.extraColumn;
var buttonEl = column.el.first().first();
me.showHideEl = Ext.get(Ext.core.DomHelper.append(buttonEl, {
tag: 'div',
style: 'position: absolute; width: 16px; height: 16px; top: 3px; cursor: pointer; left: ' + parseInt((column.el.getWidth() - 16) / 2) + 'px',
cls: me.showHideButtonIconCls,
'data-qtip': (me.renderHidden ? me.showHideButtonTooltipDo : me.showHideButtonTooltipUndo)
}));
me.showHideEl.on('click', function() {
me.setVisible(!me.isVisible());
me.showHideEl.set({
'data-qtip': (!me.isVisible() ? me.showHideButtonTooltipDo : me.showHideButtonTooltipUndo)
});
});
}

if (me.showClearAllButton && me.columns.getCount()) {
var column = me.actionColumn || me.extraColumn;
var buttonEl = column.el.first().first();
me.clearAllEl = Ext.get(Ext.core.DomHelper.append(buttonEl, {
tag: 'div',
style: 'position: absolute; width: 16px; height: 16px; top: 25px; cursor: pointer; left: ' + parseInt((column.el.getWidth() - 16) / 2) + 'px',
cls: me.clearAllButtonIconCls,
'data-qtip': me.clearAllButtonTooltip
}));

me.clearAllEl.hide();
me.clearAllEl.on('click', function() {
me.clearFilters();
});
}
},

// private
showInitialFilters: function() {
var me = this;

Ext.each(me.filterArray, function(filter) {
var column = me.columns.get(filter.property);
var field = me.fields.get(filter.property);
if(!column.getEl().hasCls(me.columnFilteredCls)) {
column.getEl().addCls(me.columnFilteredCls);
}
field.suspendEvents();
field.setValue(filter.value);
field.resumeEvents();
});

if (me.filterArray.length && me.showClearAllButton) {
me.clearAllEl.show({duration: 1000});
}
},

// private
resizeContainer: function(headerCt, col) {
var me = this;
var dataIndex = col.dataIndex;

if (!dataIndex) return;
var item = me.containers.get(dataIndex);
if (item && item.rendered) {
var itemWidth = item.getWidth();
var colWidth = me.columns.get(dataIndex).getWidth();
if (itemWidth != colWidth) {
item.setWidth(me.columns.get(dataIndex).getWidth());
item.doLayout();
}
}
},

// private
applyFilters: function(field, newVal) {
var me = this;

if (!field.isValid()) {
return;
}
var grid = me.grid;
var column = me.columns.get(field.dataIndex);
newVal = (grid.store.remoteFilter ? field.getSubmitValue() : newVal);
me.task.delay(me.updateBuffer, function() {
if (Ext.isArray(newVal) && newVal.length == 0) {
newVal = '';
}
var myIndex = -1;
Ext.each(me.filterArray, function(item2, index, allItems) {
if(item2.property === column.dataIndex) {
myIndex = index;
}
});
if(myIndex != -1) {
me.filterArray.splice(myIndex, 1);
}
if(!Ext.isEmpty(newVal)) {
if (!grid.store.remoteFilter) {
var filterFn;
switch(column.filter.operator) {
case 'eq':
filterFn = function(item) {
if (column.filter.type == 'date') {
return Ext.Date.clearTime(item.get(column.dataIndex), true).getTime() == Ext.Date.clearTime(newVal, true).getTime();
} else {
return (Ext.isEmpty(item.get(column.dataIndex)) ? me.autoStoresNullValue : item.get(column.dataIndex)) == (Ext.isEmpty(newVal) ? me.autoStoresNullValue : newVal);
}
};
break;
case 'like':
filterFn = function(item) {
var re = new RegExp(newVal, 'i');
return re.test(item.get(column.dataIndex));
};
break;
case 'in':
filterFn = function(item) {
var re = new RegExp('^' + newVal.join('|') + '$', 'i');
return re.test((Ext.isEmpty(item.get(column.dataIndex)) ? me.autoStoresNullValue : item.get(column.dataIndex)));
};
break;
}
me.filterArray.push(Ext.create('Ext.util.Filter', {
property: column.dataIndex,
filterFn: filterFn,
me: me
}));
} else {
me.filterArray.push(Ext.create('Ext.util.Filter', {
property: column.dataIndex,
value: newVal,
type: column.filter.type,
operator: column.filter.operator
}));
}
if(!column.getEl().hasCls(me.columnFilteredCls)) {
column.getEl().addCls(me.columnFilteredCls);
}
} else {
if(column.getEl().hasCls(me.columnFilteredCls)) {
column.getEl().removeCls(me.columnFilteredCls);
}
}
grid.store.currentPage = 1;
if(me.filterArray.length > 0) {
if (!grid.store.remoteFilter) grid.store.clearFilter();
grid.store.filters.clear();
grid.store.filter(me.filterArray);
if (me.clearAllEl) {
me.clearAllEl.show({duration: 1000});
}
} else {
grid.store.clearFilter();
if (me.clearAllEl) {
me.clearAllEl.hide({duration: 1000});
}
}
if (!grid.store.remoteFilter && me.autoUpdateAutoStores) {
me.fillAutoStores();
}
me.fireEvent('filterupdated', me.filterArray);
}, me);
},

//private
getFirstField: function() {
var me = this,
field = undefined;

Ext.each(me.grid.headerCt.getGridColumns(true), function(col) {
if (col.filter) {
field = me.fields.get(col.dataIndex);
return false;
}
});

return field;
},

//private
focusFirstField: function() {
var me = this;

var field = me.getFirstField();

if (field) {
field.focus(false, 200);
}
},

clearFilters: function() {
var me = this;

if (me.filterArray.length == 0) return;
me.filterArray = [];
me.fields.eachKey(function(key, field) {
field.suspendEvents();
field.reset();
field.resumeEvents();
var column = me.columns.get(key);
if(column.getEl().hasCls(Ext.baseCSSPrefix + 'column-filtered')) {
column.getEl().removeCls(Ext.baseCSSPrefix + 'column-filtered');
}
}, me);
me.grid.store.clearFilter();
if (me.clearAllEl) {
me.clearAllEl.hide({duration: 1000});
}

me.fireEvent('filterupdated', me.filterArray);
},

isVisible: function() {
var me = this;

return me.visible;
},

setVisible: function(visible) {
var me = this;

me.containers.each(function(item) {
item.setVisible(visible);
});

if (visible) {
me.focusFirstField();
}
me.grid.headerCt.doLayout();
me.visible = visible;
}
});



None of the 4.0 filter extensións seems to work correctly in all scenarios, so i've decided to create my own.
Inially i use as a base this:
http://www.sencha.com/forum/showthread.php?147553-Ext.ux.grid.HeaderFIlter
and this
http://www.sencha.com/forum/showthread.php?150918-Grid-Header-Filters

Finally last week i've rewriten the code to support all escenarios (remoteFilter true and false, grid reconfigure, etc).

I've added a lot of features like, autoConfigurated fields, autoLoaded combo stores, clearButton, clearAllButton, show/hide button, etc (See full features in the code comments).

Plugin Code and test example attached as zip.

Regards

Leonardo

scottmartin
31 Oct 2011, 12:37 PM
I like the update ... very nice. Here are a few comments:

-If I set Filter to false, the column does not display the same as the rest of the header (it displays the same as when you hover the clear all column). It should display the same as the action column that you created for clear all filter before hover.

-If I hover the 'clear all' column, the CSS is wrong ... it displays incorrectly from all the other columns

-There is a drawing delay on flex columns. You can see it resize live on the grid. I understand the reason, but is there a way to get the fix this? It makes the column look like it is rendering slow.

-It would be nice to have a setting for filter on pressing enter key, instead of a live buffer delay only.

-Thought: It 'may' be helpful to display checkboxes on a 'list' column. I figured it out quickly, but a end-user may be confused as to why the combo is not closing on selection.

-A live demo would be helpful for displaying all the features of your plugin.

I can send some screens of the drawing issues if needed.
For a first release, this is a very nice plugin!

Regards,
Scott.

scottmartin
31 Oct 2011, 1:00 PM
On reconfigure, I lose all of the columns editors for columns (filter bar is still displayed, editors missing)

Example:
I have a grid setup that displays 10 columns with filters: true for each.

When I click on a row, I have a toggle function that expands a panel to display a form and it also re-configures the grid to display 3 fields, since there is now less room on the screen for the grid due to the form.

When I perform this, I lose all of the column editors in FilterBar. Is there something that is needed to maintain the filter columns?

Code: (user click on grid row)



this.grid.getView().on('itemdblclick', function(view, record, item, index, node, e) {
this.on_toggle_form(false);
}, this);

...


on_toggle_form: function(toggle) {
if (this.form) {
if (this.form.hidden) {
this.form.show();
this.form.setVisible(true);
this.grid.reconfigure(storeUsers, colUsersMini);
} else {
if (toggle === true){
this.form.hide();
this.form.setVisible(false);
this.grid.reconfigure(storeUsers, colUsersFull);
}
}
}
},




var colUsersFull = [
{ dataIndex: 'user_name', header: 'User Name', width: 100, filter: true },
{ dataIndex: 'first_name', header: 'First Name', filter: true },
{ dataIndex: 'last_name', header: 'Last Name', filter: true },
{ dataIndex: 'level_name', header: 'Level', filter: true },
{ dataIndex: 'location_name', header: 'Location', filter: true },
{ dataIndex: 'phone', header: 'Phone', filter: true },
{ dataIndex: 'email_address', header: 'Email', flex: 1, filter: true }
];


var colUsersMini = [
{ dataIndex: 'user_name', header: 'User Name', width: 125, filter: true },
{ dataIndex: 'first_name', header: 'First Name', filter: true },
{ dataIndex: 'last_name', header: 'Last Name', filter: true },
{ dataIndex: 'level_name', header: 'Level', flex: 1, filter: true }
];


Regards,
Scott.

ldonofrio
31 Oct 2011, 3:15 PM
Thanks Scott,

Will try to answer all.

1) filter = false or not filter config columns: That is because if filter is false no container is added to the column el, so what you are viewing is "extended" column header, will try to add a dummy container to that columns maybe configurable via a css class.
2) extraColumn: Don't understand the point? Do you mean the background-color = white on hover? That's intentional, i get the idea from the saki's one that you linked. If is not, post screenshot please.
3) flex columns: I know that, seems like a bug in 4.0.7, in 4.0.2a columnresize is fired when the column's width change, doesn't matter if the user or the layout do that. In 4.0.7 only resize by the user is fired, so i've to listen to the headerCt afterlayout event. For now is the best that i can get. I suggest you wait for 4.1, i'm sure it's a bug, maybe an override looking at 4.0.2 code can work.
4) filter on enter key: I'll add it, is trivial.
5) checkboxes in multiSelect combo: This is an Ext issue, the multiSelect combos look like that by default on Ext, i've my JS/SASS override to add the check unchek icon stuff.
6) Live demo: Currently i don't have an open server to host it, will try to find one
7) Reconfigure: I remember testing something like that, i've rewrited all of this to support reconfigure, put a breakpoint, console.log on whatever in resetup method and check if is running. I'll check that tomorrow too.

Regards

Leonardo

wki01
2 Nov 2011, 2:59 AM
Great plugin.

I need two new features:

- The use of paramPrefix as in the standard filter.
- Run the submit date filter as YYYYMMDD.

thanks

ldonofrio
2 Nov 2011, 5:13 AM
1) This plugin uses the ext4 filters, so you can change that in the store server proxy (filterParam defaults to filter). Nothing to do with this
2) I'll add submitFormat = 'Y-m-d' by default to the next release, for now you can override dateTpl config option or simple pass filter: {type: 'date', submitFormat: 'Y-m-d'} in each date column

Regards
Leonardo


Great plugin.

I need two new features:

- The use of paramPrefix as in the standard filter.
- Run the submit date filter as YYYYMMDD.

thanks

Spenna
3 Nov 2011, 4:31 AM
I'm using a custom renderer for one of my columns (basically the column field is an id which i render by looking up appropriate record in a store).
How can i use this store for the combo in the filter? (the autogenerated combo only shows the original id, so perhaps you should build the combo after the grid records has been rendered..)

ldonofrio
3 Nov 2011, 5:48 AM
This plugin definitely is not going to use your column's renderer, it apply filters to the store fisical data.

I don't know why your doing that (renderer using child store thing), i suggest that you add the description field to the grid store.

If not you can use something like this


filter: {
type: 'combo',
store: 'YOUR_CHILD_STORE_ID_HERE',
valueFiled: 'YOUR_ID_HERE',
displayField: 'YOUR_DESCRIPTION_FIELD_HERE'
}

notjoshing
3 Nov 2011, 11:22 AM
Using 4.0.7, I found that the text was cut off for text fields. I switched to a Textarea instead, and that resolved the issue.

Josh

notjoshing
3 Nov 2011, 11:48 AM
When using the RowNumberer plugin, you'll get errors unless you escape the column when creating the filter header. I changed line 268 of the most recent version to do this:

if (column.filter && column.dataIndex.length ) {

Josh

ldonofrio
3 Nov 2011, 11:54 AM
Can't reproduce. Post a screenshot


Using 4.0.7, I found that the text was cut off for text fields. I switched to a Textarea instead, and that resolved the issue.

Josh

ldonofrio
3 Nov 2011, 11:56 AM
Not tested with others plugins.
RowNumber column hava a dataIndex?? Strange.
I think that you have to simply not pass "filter" to the RowNumbered column.


When using the RowNumberer plugin, you'll get errors unless you escape the column when creating the filter header. I changed line 268 of the most recent version to do this:

if (column.filter && column.dataIndex.length ) {

Josh

scottmartin
3 Nov 2011, 12:18 PM
@Leonardo

Here is the screen of what I am talking about. If I set filter: false for a column in the middle of the grid, it displays correctly .. the color of the header:

Correct:
29013

If I do the same on the first column, it displays incorrectly as:

29014

This is also how the last column displays when I hover to select the 'clear all filter' that you create

Edit: I believe the above issue has to do with the sorting icon, but it still gives you an idea on how the clear all displays on hover without any text/icon

Regards,
Scott

scottmartin
3 Nov 2011, 12:32 PM
Column without filterBar:
29015

Column with filterBar:
29016

If you hover the column with filter, then it displays as first image.

Regards,
Scott.

ldonofrio
3 Nov 2011, 12:57 PM
Scott if i undertand.
Seems that you are talking about the css gradient that is expanded.
I was using grey theme and doen't note that.

Is a sass thing, i'll try to fix it but really it doen't matter for me.

Regards,

Leonardo

notjoshing
4 Nov 2011, 9:31 AM
I didn't dig into the RowNumberer internals to see, but from what I've seen before it's essentially creating another column which can be customized like any other. There may be more to this, and I'll try to remember to look into it when I'm done coding what I'm working on.

SMMJ_Dev
7 Nov 2011, 7:23 AM
Nice, I can't wait to check it out. I have had absolutely no time to show all my updates and extensions I created. Not to mention the updates for 4.1. I will definitely take a look at this to see if I can't bring something together for more elegant solutions for my 4.1 updates.

In order to get the filters working correctly with resizing and moving of columns I had to override the HeaderResizer plugin for column resizing and DropZone code for moving columns around. I think I might be able to fix the issue calling doComponentLayout on different grid events, but I have not tried it yet. I have posted a bug and they are working on it, so I might not have to do this once they update for the bug. :)

ldonofrio
7 Nov 2011, 7:44 AM
Thanks SMMJ for your first approach!

scottmartin
8 Nov 2011, 11:48 AM
@Leonardo:


2) extraColumn: Don't understand the point? Do you mean the background-color = white on hover? That's intentional, i get the idea from the saki's one that you linked. If is not, post screenshot please.

Here is what I am referring to on the extra column.

If you look at the example from Saki, it displays the 'X' for clear all where the grid scrollbar would even if there is no scrollbar.

(1 space)
29146

In your version it creates an extra column beside the scrollbar space would go and you now have 2 spaces at the end of your grid.

(2 spaces)
29147

If you could update it to just use the space over the scrollbar, that would look much better.

Again, looking at the example:
http://www.sencha-addons.com/public/gms/examples/index.html
(http://www.sencha-addons.com/public/gms/examples/index.html)
If you resize the window to display the scrollbar, there is no change in the spacing.

Regards,
Scott.

ldonofrio
8 Nov 2011, 3:34 PM
Ext 3.x always reserves space for vertical scrollbar, Ext4 shows/hides the scroller on demands.
I've nothing to do with this, i can`t trust in 4 scroller.

scottmartin
11 Nov 2011, 5:48 AM
Any updates in the pipe? Just curious.

Regards,
Scott.

ldonofrio
11 Nov 2011, 6:23 AM
only this


* @updated 2011-11-02 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)

* Filter on ENTER

* Defaults submitFormat on date filter to 'Y-m-d' and use that in applyFilters for local filtering

* Added null value support on combo and list filters (autoStoresNullValue and autoStoresNullText)

* Fixed some combo styles

* @updated 2011-11-10 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)

* Parse and show initial filters applied to the store (only property -> value filters, filterFn is unsuported)


Let me know if you are interested

scottmartin
11 Nov 2011, 6:37 AM
Let me know if you are interested

Sure. Post it if you would please.

Regards,
Scott.

ldonofrio
11 Nov 2011, 8:11 AM
updated code attached
29235

scottmartin
11 Nov 2011, 8:18 AM
Thank you sir.

Regards,
Scott.

wki01
14 Nov 2011, 12:43 AM
I have a paged grid with filtering. If I page to say page 9, then select a filter, which filters down to 1 page, the "start" value I get on the server is still where it was while at page 9. So for example, it will say page 9 of 1 - and no data displayed. Very confusing for the users.

Can I get the "start" to reset back to 1 when filtering ?


Thank you

ldonofrio
14 Nov 2011, 4:45 AM
You're right

Put this:


grid.store.currentPage = 1


In line 703
Just before "if (me.filterArray.lenght > 0)"



I have a paged grid with filtering. If I page to say page 9, then select a filter, which filters down to 1 page, the "start" value I get on the server is still where it was while at page 9. So for example, it will say page 9 of 1 - and no data displayed. Very confusing for the users.

Can I get the "start" to reset back to 1 when filtering ?


Thank you

wki01
15 Nov 2011, 1:51 AM
The last update does not work onIE9.
ThefilterBaris not displayed.
Everythingok onFF andChrome.

I noticed that was not posted on the front page.
It is notan official version?


thanks

ldonofrio
15 Nov 2011, 5:23 AM
Can't reproduce, works on ie9, see screenshot, are you getting errors?
Official, don't have time to update the post right now.
29293


The last update does not work onIE9.
ThefilterBaris not displayed.
Everythingok onFF andChrome.

I noticed that was not posted on the front page.
It is notan official version?


thanks

wki01
15 Nov 2011, 5:55 AM
I'm sorry,
My mistake.
It is not a browser problem, a problem that after hiding the filterbar even if I press the button to view is no longer displayed
thanks




29295

wki01
15 Nov 2011, 8:25 AM
I can not understand why, but removing this line,everything works as before.
thanks



container.on('afterrender', function(cnt) {
//me.rowHeight = cnt.getHeight();
var delayedFn = function() {
this.resizeContainer(cnt.dataIndex);
};

ldonofrio
15 Nov 2011, 8:34 AM
that line try to calculate the container height on render, otherwise it's fixed to 23px, if you're using the default theme you'll not have any problems removing that line.

scottmartin
20 Nov 2011, 10:30 AM
@ldonofrio

It would be nice to allow for operators in numeric fields to filter:

>50000
<50000
>=50000
<=50000
=45000

In looking at your code, currently I could set filter: 'string' and then have the server handle the filter?

Regards,
Scott.

ldonofrio
21 Nov 2011, 5:13 AM
the plugin is prepared to do that, but is not complete, the only thing missing is the UI to allow operators selection.

If you look at the code the plugin is overridding the server proxy to send "type" and "operator" properties to the server.

If you do:
filter: {
type: 'int',
operator: 'gt'
}

you'll receive the operator at serser side.

Regards

allan.ditzel
1 Dec 2011, 12:53 PM
Does anyone have a sample app/code that they can share? I've installed the plugin, but I don't see any filtering available anywhere. In the browser dev tools I can see that the filter bar js file has loaded, and also its dependency of ClearButton. I don't see any errors in the console, either.

Thanks,

Allan

ldonofrio
1 Dec 2011, 1:07 PM
Have you setup "filter" property for your columns?
Start with filter: true in a column

allan.ditzel
1 Dec 2011, 1:19 PM
When I do that now I get an error in the console saying:

Uncaught TypeError: Object [object Object] has no method 'getEditor' on line 79359 of ext-all-debug.js and the application fails to render properly.

scottmartin
2 Dec 2011, 5:48 AM
You might want to show your code. Do you have ClearButton.js in your path for the editors?

Code:



var columns = [
{ dataIndex: 'id_client', header: 'ID', width: 50, filter: 'string' },
{ dataIndex: 'last_name', header: 'Last', filter: true },
{ dataIndex: 'first_name', header: 'First', filter: true }
];




createGrid: function(){
this.grid = Ext.create('widget.app.clients-gridclients', {
xtype: 'app.clients-gridclients',
id: 'grid-clients',
region: 'center',
plugins: [{
ptype: 'filterbar',
renderHidden: false,
showClearButton: true
}],
store: this.store,
border: false
});


// use this to load data on start
this.on_filter_reset();
return this.grid;
},

Regards,
Scott.

ldonofrio
2 Dec 2011, 5:58 AM
getEditor is not related to filterBar, maybe you have an error in your editor grid, post your code

allan.ditzel
2 Dec 2011, 8:43 AM
Scott, thank you for the code!

Idonofrio, here's my grid code:



{
xtype: 'gridpanel',
id: 'gridId',
store: 'datastore',
flex: 1,
viewConfig: {


},
columns: [
{
xtype: 'gridcolumn',
dataIndex: 'name',
editor: 'textfield',
flex: 1,
text: 'Name',
filter: 'string'
},
{
xtype: 'gridcolumn',
dataIndex: 'description',
editor: 'textfield',
flex: 1,
text: 'Description'
},
{
xtype: 'gridcolumn',
dataIndex: 'status',
text: 'Status'
}
],
plugins: [
Ext.create('Ext.grid.plugin.RowEditing', {


}),
{
ptype: 'filterbar',
renderHidden: false,
showClearButton: true
}
],
selModel: Ext.create('Ext.selection.CheckboxModel', {


})
}


Setting the filter on the first column to either filter: true OR filter: 'string' yields the same error.

allan.ditzel
2 Dec 2011, 11:15 AM
Hi Scott,

I forgot to include this in my earlier reply, but yes, I do have ClearButton available. I see the class being loaded in by the browser.

ldonofrio
2 Dec 2011, 12:32 PM
the error is fired in RowEditor plugin, i'm not using my plugin with that.

allan.ditzel
2 Dec 2011, 6:31 PM
Yup, I can confirm that removing the RowEditing plugin allows the filterbar to work correctly. So it seems that they're incompatible.

allan.ditzel
2 Dec 2011, 8:35 PM
However, if you add the filter bar before the rowediting plugin it works.

TiloS
13 Dec 2011, 5:52 AM
Hello,

I tryed the downloaded example and firefox and IE9 give me an error in the ext-all.js of ExtJs 4.0.2a.
Firebug: "g is undefined"
IE9: For "substring" cannot called a value, the object is undefined".


var grid = Ext.create('Ext.grid.Panel', {
store: store,
plugins: [{
ptype: 'filterbar',
renderHidden: false,
}],
forceFit: false,
columns: [
{
text : 'Company',
flex : 1,
dataIndex: 'company',
filter: true
}
],
title: 'Array Grid',
viewConfig: {
stripeRows: true
}
});
If I use it without "filter: true" there is no error.
What could it be?

Tilo

ldonofrio
13 Dec 2011, 6:01 AM
extra comma after renderHidden: false
are you including ClearButton ux?
have you tried 4.0.7?

TiloS
13 Dec 2011, 6:22 AM
I did not include ClearButton. Now it works.

Thank you
Tilo

TiloS
13 Dec 2011, 6:53 AM
I include the ClearButton.css and I see the clear buttons in the filter fields but I don't see the "Clear all filters" icon and also the style of the filtered column headers are not changed. I think I still need a css, where I can find it?

ldonofrio
13 Dec 2011, 7:09 AM
You have to code the css classes in sass/css
for example
column filtered (sass)


.#{$prefix}grid-header-ct .#{$prefix}column-filtered .#{$prefix}column-header-inner .#{$prefix}column-header-text {
font-weight: bold;
font-style: italic;
color: $ah-color;
}


clear filters icon (css)


.clear-filters
{
background-image: url( ../images/clear-filters.png ) !important;
}

ldonofrio
13 Dec 2011, 7:12 AM
I've posted my latest code in the first post.......

Sheraton
20 Dec 2011, 12:31 AM
ok thank's you !

jeltok
22 Dec 2011, 7:40 AM
Thanks for the great plugin.

kevhender
30 Dec 2011, 1:12 PM
This plugin is excellent, great work! Any chance you can get it working in 4.1-beta? Thanks!

ldonofrio
2 Jan 2012, 4:15 AM
The technique used in this plugin doen't work on 4.1, so i think i have to redesign it.
Also my entire app is broken on 4.1, so i've decided to whait for an stable versión.

kevhender
3 Jan 2012, 5:20 AM
Could you elaborate on what you mean by that? What "technique" no longer works in 4.1? I'd like to try to modify it myself if possible... Thanks!

ldonofrio
3 Jan 2012, 5:24 AM
i've tried yesterday, and the basic functionallity works, but seems that 4.1 have problems with the headerCt layout when the grid is inside a container (fit, border, etc), no problem rendering the grid to the dom

kevhender
4 Jan 2012, 6:18 AM
FYI - I changed the 'afterrender' listener around line 524 to an 'afterlayout' listener, and it seemed to fix most problems. Could be a patch for folks using this until you're able to get it working fully with 4.1. Thanks again for the great work.

TiloS
20 Jan 2012, 1:13 AM
Hello kevhender,
that are good news that it can be fix for 4.1.
Could you post the changed code of the plugin.

ana.cristina.ionescu
23 Jan 2012, 4:18 AM
Should this plugin work also on remote stores?

I am using Ext 4.0.7 and when adding filter: true to columns , I am getting the follwing error:

namespace is undefined
http://localhost/../ext/ext-all-debug.js
Line 3647

Hope you can help me.
thanks!

ldonofrio
23 Jan 2012, 5:08 AM
it works, make sure that you're including Ext.ux.ClearButton extensión.

Should this plugin work also on remote stores?

I am using Ext 4.0.7 and when adding filter: true to columns , I am getting the follwing error:

namespace is undefined
http://localhost/../ext/ext-all-debug.js
Line 3647

Hope you can help me.
thanks!

ana.cristina.ionescu
23 Jan 2012, 5:16 AM
Thanks! ClearButton was the problem.

Another question : is there something that I have to set to work with remote stores?

Thank you,
Ana

ldonofrio
23 Jan 2012, 5:20 AM
You're welcome.

Set remoteFilter: true in the store and write your server logic to process "filters" array (property, value, operator and type properties are posted for each item)

masoud_tamizy
18 Feb 2012, 5:35 AM
why when i want to use this plugin , after i insert this line :
<script type="text/javascript" src="JS/FilterBar.js">
i encounter this error :
31871
error 404 (not found) clearbutton.js !!!

ana.cristina.ionescu
18 Feb 2012, 5:39 AM
Hi,

Search on web for Ext.ux.form.field.ClearButton and you will find ClearButton.js. then you should add this to : examples/ux/form/field. And this is it!

Ana

TiloS
18 Feb 2012, 5:44 AM
I would like to use this plugin in my project in 4.1.b2. It's working in 4.0.7 so nice but I changed already to 4.1.b2 (because of the scrollbar issues in grid).
So I tryed to fit the plugin and replaced the line 524 with
container.on('afterlayout', function(cnt) {So at least I can see the filter fields.
But the width of the textfileds don't adjust to the width of the column. The other fields are ok, only the textfield not. Also inside the plugin I cannot change the width, I tryed this:
stringTpl: {
xtype: 'textfield',
operator: 'like',
width: 100,
size: 10
},- there is no change.


Another point (independent from the ExtJs version), when the store is already filtered local and I want to filter additional with the filterbar the original filter is removed. Is it possible not to remove the original filter so that I can use the filterbar as additional filter?

TiloS
18 Feb 2012, 10:01 AM
The textfield width is solved, I used a css from 4.0.7. When I use css from 4.1.b2 the textfield is correct.

But how about the other point, to add the filtering to an existing local filter?

TiloS
19 Feb 2012, 11:55 AM
I have looked at the plugin and I see that there it tries to parse initial filters. But I use filters with filterFn and this is unfortunatly not supported yet.

Is it possible to include parsing filterFn in the next plugin version for 4.1? Else I will try to do it myself.

zilnuken
19 Feb 2012, 10:04 PM
Hello this is my example 31920 of implementation FilterBar + RowNumbered + Remote ComboBox Filter :D thanks ldonofrio

masoud_tamizy
20 Feb 2012, 10:29 PM
why when i add this plugin in my row-editing grid , i encounter this error :
Uncaught TypeError: Cannot call method 'substring' of undefined

and how can i define an datefield ?

thanks zilnuken (http://www.sencha.com/forum/member.php?368768-zilnuken) for your sample code and ldonofrio for this plugin :)

januzis
28 Feb 2012, 6:20 AM
Any plans to make FilterBar plugin remember filters set using state manager?

mxu
29 Feb 2012, 10:03 AM
hello,

I need to use a buffered grid since records to load ca go over 5000,
does grid filtering feature work on a buffered grid ?

thanks

mxu

januzis
29 Feb 2012, 11:54 PM
hello,

I need to use a buffered grid since records to load ca go over 5000,
does grid filtering feature work on a buffered grid ?

thanks

mxu

You really don't need any buffering for 5000 records.. As someone mentioned in performance thread, it's better to load everything up in browser's memory, until certain number of records, but that number is closer to 100K than 5k. These filters are capable of filtering remotely, though (they use store filters).

predator
4 Mar 2012, 1:51 PM
32375

I was working on implementing different operators for the sql queries. Great UX by the way... I think that finally they are working as expected.. however at the end I tried to finish the ui by adding the css to the showhide and clearall buttons. however the standart css declarations seems to render the icons a little off.

Is there anyone that can tell me why?

here is the declaration i have in css


.gear--pencil {background-image: url("../images/icons/gear--pencil.png") !important}


Any comment is greatly appreciated.

another_i
22 Mar 2012, 4:16 AM
Good work! Great UX.

If grid use Ext.selection.CheckboxModel function focusFirstField throw next error:

Uncaught TypeError: Cannot call method 'focus' of undefined /ext4/ux/grid/FilterBar.js:729


This focusFirstField function fix works for me:


focusFirstField: function() {
var me = this;


if (!me.columns.getCount()) return;


var field = me.fields.get(me.grid.headerCt.items.getAt(0).dataIndex);
//field.focus();
!field || (field.focus()); // FIX HERE
},


But i have some troubles:
First with header of Ext.selection.CheckboxModel column when FilterBar hidden.
33003


And second updated code by ldonofrio (11-11-2011 20:11:47) work worse for me because FilterBar for some grids is not rendered. And it's looks like on the top screenshot. And I don't know why. Thanks.

ldonofrio
22 Mar 2012, 6:51 AM
I've updated code fixing your issues.

See attach file (can't edit the first post, forum goes crazy)
33014

another_i
22 Mar 2012, 11:05 PM
ldonofrio​, thank you very much!

ldonofrio
26 Apr 2012, 10:55 AM
I've updated the first post with new code for 4.1.

Enjoy!

heovitcon
27 Apr 2012, 1:16 PM
32375

I was working on implementing different operators for the sql queries. Great UX by the way... I think that finally they are working as expected.. however at the end I tried to finish the ui by adding the css to the showhide and clearall buttons. however the standart css declarations seems to render the icons a little off.

Is there anyone that can tell me why?

here is the declaration i have in css


.gear--pencil {background-image: url("../images/icons/gear--pencil.png") !important}


Any comment is greatly appreciated.

Do you public your version? I really like it.

another_i
31 May 2012, 3:34 AM
Thank you for version for ExtJS 4.1! Great!=D>

But there is some issue to fix:
* Intercept column's setPadding for all columns except actionColumn or extraColumn (fix checkBoxSelectionModel header)


— not bad but when checkBoxSelectionModel header is rendered it have next style:


element.style {
height: 22px;
padding-top: 4px;
}



Can you fix setPadding for checkBoxSelectionModel header and set:
padding-top: 4px;


Thanks.

ldonofrio
31 May 2012, 7:22 AM
done, updated in the first post.


Thank you for version for ExtJS 4.1! Great!=D>

But there is some issue to fix:
* Intercept column's setPadding for all columns except actionColumn or extraColumn (fix checkBoxSelectionModel header)


— not bad but when checkBoxSelectionModel header is rendered it have next style:


element.style {
height: 22px;
padding-top: 4px;
}



Can you fix setPadding for checkBoxSelectionModel header and set:
padding-top: 4px;


Thanks.

another_i
31 May 2012, 10:00 PM
No changes. :-|
35823

ldonofrio
1 Jun 2012, 4:55 AM
code was not updated in the first post, don't know why but i can't do it.
reprace de interceptor function in renderFilterBar private method by this:


column.setPadding = Ext.Function.createInterceptor(column.setPadding, function(h) {
if (column.text == ' ') { //checkbox column
this.titleEl.setStyle({
paddingTop: '4px'
});
}
return false;
});

scottmartin
1 Jun 2012, 5:13 AM
If you post the latest code, I can see about updating 1st post and deleting new.

Scott.

another_i
1 Jun 2012, 5:41 AM
I think that more correct will be next code:
...
if (column.hasCls('x-column-header-checkbox')){ //checkbox column
...

And thank you for job! :)

ldonofrio
1 Jun 2012, 5:47 AM
you're right but in this case the correct code is:

column.hasCls(Ext.baseCSSPrefix + 'column-header-checkbox')

to allow sandboxing...

scottmartin
1 Jun 2012, 6:02 AM
Updated.

Scott.

alessiom
23 Jul 2012, 1:18 AM
Hi all,
thank you for this plugin.
Is it possible to filter date and number by range?

Thank you
Alessio

ldonofrio
30 Jul 2012, 6:59 AM
Last version on Sencha Market
https://market.sencha.com/users/68/addons/95

(http://market.sencha.com/users/68/addons/95)

another_i
3 Aug 2012, 3:25 AM
Great. Thank you!
And what about more complex filtering (equal, great than (or equal), less than (or equal)) of numbers and dates? Do you planing do this?

ldonofrio
3 Aug 2012, 8:23 AM
Yes, i have that, currently i'm testing the new versión, i'll upload it to market next week.

Regards

Leonardo


Great. Thank you!
And what about more complex filtering (equal, great than (or equal), less than (or equal)) of numbers and dates? Do you planing do this?

lain_hacker@naver.com
20 Aug 2012, 1:51 AM
FillterBar indeed thank you. However, there's a bug. It was meant less as a post, please understand, even if wrong.


Form the filter tab and move the location, the size of a large grid of the form if the form is an area outside the mask does not match the location and the location of the grid do not.
38082

SunboX
22 Aug 2012, 12:54 AM
Fixed render extra column bug for grid without action column(s)


/** * Plugin that enable filters on the grid headers.<br>
* The header filters are integrated with new Ext4 <code>Ext.data.Store</code> filters.<br>
*
* @author Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* @version 1.0 (supports 4.1.1)
* @updated 2011-10-18 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Support renderHidden config option, isVisible(), and setVisible() methods (added getFilterBar() method to the grid)
* Fix filter bug that append filters to Store filters MixedCollection
* Fix layout broken on initial render when columns have width property
* @updated 2011-10-24 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Rendering code rewrited, filters are now rendered inside de column headers, this solves scrollable grids issues, now scroll, columnMove, and columnHide/Show is handled by the headerCt
* Support showClearButton config option, render a clear Button for each filter to clear the applied filter (uses Ext.ux.form.field.ClearButton plugin)
* Added clearFilters() method.
* @updated 2011-10-25 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Allow preconfigured filter's types and auto based on store field data types
* Auto generated stores for combo and list filters (local collect or server in autoStoresRemoteProperty response property)
* @updated 2011-10-26 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Completelly rewriten to support reconfigure filters on grid's reconfigure
* Supports clearAll and showHide buttons rendered in an actioncolumn or in new generetad small column
* @updated 2011-10-27 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Added support to 4.0.7 (columnresize not fired correctly on this build)
* @updated 2011-11-02 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Filter on ENTER
* Defaults submitFormat on date filter to 'Y-m-d' and use that in applyFilters for local filtering
* Added null value support on combo and list filters (autoStoresNullValue and autoStoresNullText)
* Fixed some combo styles
* @updated 2011-11-10 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Parse and show initial filters applied to the store (only property -> value filters, filterFn is unsuported)
* @updated 2011-12-12 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Extends AbstractPlugin and use Observable as a Mixin
* Yes/No localization on constructor
* @updated 2012-01-03 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Added some support for 4.1 beta
* @updated 2012-01-05 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* 99% support for 4.1 beta. Seems to be working
* @updated 2012-03-22 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Fix focusFirstField method
* Allow to specify listConfig in combo filter
* Intercept column's setPadding for all columns except actionColumn or extraColumn (fix checkBoxSelectionModel header)
* @updated 2012-05-07 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Fully tested on 4.1 final
* @updated 2012-05-31 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Fix padding issue on checkbox column
* @updated 2012-07-10 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Add msgTarget: none to field to fix overridding msgTarget to side in fields in 4.1.1
* @updated 2012-07-26 by Ing. Leonardo D'Onofrio (leonardo_donofrio at hotmail.com)
* Fixed sort on enter bug regression
* add checkChangeBuffer: 50 to field, this way works as expected if this config is globally overridden
* private method applyFilters refactored to support delayed (key events) and instant filters (enter key and combo/picker select event)
* @updated 2012-08-22 by Dipl-Ing. (FH) André Fiedler (http://twitter.com/sonnenkiste)
* Fixed render extra column bug for grid without action column(s)
*/


Ext.define('Ext.ux.grid.FilterBar', {
extend: 'Ext.AbstractPlugin',
alias: 'plugin.filterbar',
uses: [
'Ext.window.MessageBox',
'Ext.ux.form.field.ClearButton',
'Ext.container.Container',
'Ext.util.DelayedTask',
'Ext.layout.container.HBox',
'Ext.data.ArrayStore',
'Ext.button.Button',
'Ext.form.field.Text',
'Ext.form.field.Number',
'Ext.form.field.Date',
'Ext.form.field.ComboBox'
],
mixins: {
observable: 'Ext.util.Observable'
},


updateBuffer : 800, // buffer time to apply filtering when typing/selecting


columnFilteredCls : Ext.baseCSSPrefix + 'column-filtered', // CSS class to apply to the filtered column header


renderHidden : true, // renders the filters hidden by default, use in combination with showShowHideButton
showShowHideButton : true, // add show/hide button in actioncolumn header if found, if not a new small column is created
showHideButtonTooltipDo : 'Show filter bar', // button tooltip show
showHideButtonTooltipUndo : 'Hide filter bar', // button tooltip hide
showHideButtonIconCls : 'filter', // button iconCls


showClearButton : true, // use Ext.ux.form.field.ClearButton to allow user to clear each filter, the same as showShowHideButton
showClearAllButton : true, // add clearAll button in actioncolumn header if found, if not a new small column is created
clearAllButtonIconCls : 'clear-filters', // css class with the icon of the clear all button
clearAllButtonTooltip : 'Clear all filters', // button tooltip


autoStoresRemoteProperty : 'autoStores', // if no store is configured for a combo filter then stores are created automatically, if remoteFilter is true then use this property to return arrayStores from the server
autoStoresNullValue : '###NULL###', // value send to the server to expecify null filter
autoStoresNullText : '[empty]', // NULL Display Text
autoUpdateAutoStores : false, // if set to true combo autoStores are updated each time that a filter is applied


boolTpl: {
xtype: 'combo',
queryMode: 'local',
forceSelection: true,
triggerAction: 'all',
editable: false,
store: [
[1, 'Yes'],
[0, 'No']
],
operator: 'eq'
},
dateTpl: {
xtype: 'datefield',
editable: true,
submitFormat: 'Y-m-d',
operator: 'eq'
},
floatTpl: {
xtype: 'numberfield',
allowDecimals: true,
minValue: 0,
hideTrigger: true,
keyNavEnabled: false,
mouseWheelEnabled: false,
operator: 'eq'
},
intTpl: {
xtype: 'numberfield',
allowDecimals: false,
minValue: 0,
operator: 'eq'
},
stringTpl: {
xtype: 'textfield',
operator: 'like'
},
comboTpl: {
xtype: 'combo',
queryMode: 'local',
forceSelection: true,
editable: false,
triggerAction: 'all',
operator: 'eq'
},
listTpl: {
xtype: 'combo',
queryMode: 'local',
forceSelection: true,
editable: false,
triggerAction: 'all',
multiSelect: true,
operator: 'in'
},


constructor: function() {
var me = this;


me.boolTpl.store[0][1] = Ext.MessageBox.buttonText.yes;
me.boolTpl.store[1][1] = Ext.MessageBox.buttonText.no;


me.mixins.observable.constructor.call(me);
me.callParent(arguments);
},


// private
init: function(grid) {
var me = this;


grid.on({
columnresize: me.resizeContainer,
columnhide: me.resizeContainer,
columnshow: me.resizeContainer,
beforedestroy: me.unsetup,
reconfigure: me.resetup,
scope: me
});


grid.addEvents('filterupdated');


Ext.apply(grid, {
filterBar: me,
getFilterBar: function() {
return this.filterBar;
}
});


me.setup(grid);
},


// private
setup: function(grid) {
var me = this;


me.grid = grid;
me.visible = !me.renderHidden;
me.autoStores = Ext.create('Ext.util.MixedCollection');
me.autoStoresLoaded = false;
me.columns = Ext.create('Ext.util.MixedCollection');
me.containers = Ext.create('Ext.util.MixedCollection');
me.fields = Ext.create('Ext.util.MixedCollection');
me.actionColumn = me.grid.down('actioncolumn') || me.grid.down('actioncolumnpro');
me.extraColumn = null;
me.clearAllEl = null;
me.showHideEl = null;
me.task = Ext.create('Ext.util.DelayedTask');
me.filterArray = [];


me.overrideProxy();
me.parseFiltersConfig(); // sets me.columns and me.autoStores
me.parseInitialFilters(); // sets me.filterArray with the store previous filters if any (adds operator and type if missing)


// renders the filter's bar
if (grid.rendered) {
me.renderFilterBar(grid);
} else {
grid.on('afterrender', me.renderFilterBar, me, { single: true });
}
},


// private
unsetup: function(grid) {
var me = this;


if (me.autoStores.getCount()) {
me.grid.store.un('load', me.fillAutoStores, me);
}


me.autoStores.each(function(item) {
Ext.destroy(item);
});
me.autoStores.clear();
me.autoStores = null;
me.columns.each(function(column) {
if (column.rendered) {
if(column.getEl().hasCls(me.columnFilteredCls)) {
column.getEl().removeCls(me.columnFilteredCls);
}
}
}, me);
me.columns.clear();
me.columns = null;
me.fields.each(function(item) {
Ext.destroy(item);
});
me.fields.clear();
me.fields = null;
me.containers.each(function(item) {
Ext.destroy(item);
});
me.containers.clear();
me.containers = null;
if (me.clearAllEl) {
Ext.destroy(me.clearAllEl);
me.clearAllEl = null;
}
if (me.showHideEl) {
Ext.destroy(me.showHideEl);
me.showHideEl = null;
}
if (me.extraColumn) {
me.grid.headerCt.items.remove(me.extraColumn);
Ext.destroy(me.extraColumn);
me.extraColumn = null;
}
me.task = null;
me.filterArray = null;
},


// private
resetup: function(grid) {
var me = this;


me.unsetup(grid);
me.setup(grid);
},


// private
overrideProxy: function() {
var me = this;


// override encodeFilters to append type and operator in remote filtering
Ext.apply(me.grid.store.proxy, {
encodeFilters: function(filters) {
var min = [],
length = filters.length,
i = 0;


for (; i < length; i++) {
min[i] = {
property: filters[i].property,
value : filters[i].value
};
if (filters[i].type) {
min[i].type = filters[i].type;
}
if (filters[i].operator) {
min[i].operator = filters[i].operator;
}
}
return this.applyEncoding(min);
}
});
},


// private
parseFiltersConfig: function() {
var me = this;
var columns = this.grid.headerCt.getGridColumns(true);
me.columns.clear();
me.autoStores.clear();
Ext.each(columns, function(column) {
if (column.filter) {
if (column.filter === true || column.filter === 'auto') { // automatic types configuration (store based)
var type = me.grid.store.model.prototype.fields.get(column.dataIndex).type.type;
if (type == 'auto') type = 'string';
column.filter = type;
}
if (Ext.isString(column.filter)) {
column.filter = {
type: column.filter // only set type to then use templates
};
}
if (column.filter.type) {
column.filter = Ext.applyIf(column.filter, me[column.filter.type + 'Tpl']); // also use templates but with user configuration
}


if (column.filter.xtype == 'combo' && !column.filter.store) {
column.autoStore = true;
column.filter.store = Ext.create('Ext.data.ArrayStore', {
fields: [{
name: 'text'
},{
name: 'id'
}]
});
me.autoStores.add(column.dataIndex, column.filter.store);
column.filter = Ext.apply(column.filter, {
displayField: 'text',
valueField: 'id'
});
}


if (!column.filter.type) {
switch(column.filter.xtype) {
case 'combo':
column.filter.type = (column.filter.multiSelect ? 'list' : 'combo');
break;
case 'datefield':
column.filter.type = 'date';
break;
case 'numberfield':
column.filter.type = (column.filter.allowDecimals ? 'float' : 'int');
break;
default:
column.filter.type = 'string'
}
}


if (!column.filter.operator) {
column.filter.operator = me[column.filter.type + 'Tpl'].operator;
}
me.columns.add(column.dataIndex, column);
}
}, me);
if (me.autoStores.getCount()) {
if (me.grid.store.getCount() > 0) {
me.fillAutoStores(me.grid.store);
}
if (me.grid.store.remoteFilter) {
var autoStores = [];
me.autoStores.eachKey(function(key, item) {
autoStores.push(key);
});
me.grid.store.proxy.extraParams = me.grid.store.proxy.extraParams || {};
me.grid.store.proxy.extraParams[me.autoStoresRemoteProperty] = autoStores;
}
me.grid.store.on('load', me.fillAutoStores, me);
}
},


// private
fillAutoStores: function(store) {
var me = this;


if (!me.autoUpdateAutoStores && me.autoStoresLoaded) return;


me.autoStores.eachKey(function(key, item) {
var field = me.fields.get(key);
if (field) {
field.suspendEvents();
var fieldValue = field.getValue();
}
if (!store.remoteFilter) { // values from local store
var data = store.collect(key, true, false).sort();
var records = [];
Ext.each(data, function(txt) {
if (Ext.isEmpty(txt)) {
Ext.Array.insert(records, 0, [{
text: me.autoStoresNullText,
id: me.autoStoresNullValue
}]);
} else {
records.push({
text: txt,
id: txt
});
}
});
item.loadData(records);
} else { // values from server
if (store.proxy.reader.rawData[me.autoStoresRemoteProperty]) {
var data = store.proxy.reader.rawData[me.autoStoresRemoteProperty];
if (data[key]) {
var records = [];
Ext.each(data[key].sort(), function(txt) {
if (Ext.isEmpty(txt)) {
Ext.Array.insert(records, 0, [{
text: me.autoStoresNullText,
id: me.autoStoresNullValue
}]);
} else {
records.push({
text: txt,
id: txt
});
}
});
item.loadData(records);
}
}
}
if (field) {
field.setValue(fieldValue);
field.resumeEvents();
}
}, me);
me.autoStoresLoaded = true;
if (me.grid.store.remoteFilter && !me.autoUpdateAutoStores) {
delete me.grid.store.proxy.extraParams[me.autoStoresRemoteProperty];
}
},


// private
parseInitialFilters: function() {
var me = this;


me.filterArray = [];
me.grid.store.filters.each(function(filter) {
// try to parse initial filters, for now filterFn is unsuported
if (filter.property && !Ext.isEmpty(filter.value) && me.columns.get(filter.property)) {
if (!filter.type) filter.type = me.columns.get(filter.property).filter.type;
if (!filter.operator) filter.operator = me.columns.get(filter.property).filter.operator;
me.filterArray.push(filter);
}
}, me);
},


// private
renderFilterBar: function(grid) {
var me = this;


me.containers.clear();
me.fields.clear();
me.columns.eachKey(function(key, column) {
var listConfig = column.filter.listConfig || {};
listConfig = Ext.apply(listConfig, {
style: 'border-top-width: 1px'
});
var field = Ext.widget(column.filter.xtype, Ext.apply(column.filter, {
dataIndex: key,
flex: 1,
margin: 0,
fieldStyle: 'border-left-width: 0px; border-bottom-width: 0px;',
listConfig: listConfig,
preventMark: true,
msgTarget: 'none',
checkChangeBuffer: 50,
enableKeyEvents: true,
listeners: {
change: me.applyDelayedFilters,
select: me.applyInstantFilters,
keypress: function(txt, e) {
if(e.getCharCode() == 13) {
e.stopEvent();
me.applyInstantFilters(txt);
}
return false;
},
scope: me
},
plugins: (!me.showClearButton ? [] : [{
ptype: 'clearbutton'
}])
}));
me.fields.add(column.dataIndex, field);
var container = Ext.create('Ext.container.Container', {
dataIndex: key,
layout: 'hbox',
bodyStyle: 'background-color: "transparent";',
width: column.getWidth(),
items: [field],
listeners: {
scope: me,
element: 'el',
mousedown: function(e) { e.stopPropagation(); },
click: function(e) { e.stopPropagation(); },
dblclick: function(e) { e.stopPropagation(); },
keydown: function(e) { e.stopPropagation(); },
keypress: function(e) { e.stopPropagation(); },
keyup: function(e) { e.stopPropagation(); }
}
});
me.containers.add(column.dataIndex, container);
container.render(Ext.get(column.id));
}, me);
var excludedCols = [];
if (me.actionColumn) excludedCols.push(me.actionColumn.id);
if (me.extraColumn) excludedCols.push(me.extraColumn.id);
Ext.each(me.grid.headerCt.getGridColumns(true), function(column) {
if (!Ext.Array.contains(excludedCols, column.id)) {
column.setPadding = Ext.Function.createInterceptor(column.setPadding, function(h) {
if (column.hasCls(Ext.baseCSSPrefix + 'column-header-checkbox')) { //checkbox column
this.titleEl.setStyle({
paddingTop: '4px'
});
}
return false;
});
}
});




me.setVisible(me.visible);


me.renderButtons();


me.showInitialFilters();
},


//private
renderButtons: function() {
var me = this,
column = me.actionColumn || me.extraColumn;


if (column && me.showShowHideButton && me.columns.getCount()) {
var column = me.actionColumn || me.extraColumn;
var buttonEl = column.el.first().first();
me.showHideEl = Ext.get(Ext.core.DomHelper.append(buttonEl, {
tag: 'div',
style: 'position: absolute; width: 16px; height: 16px; top: 3px; cursor: pointer; left: ' + parseInt((column.el.getWidth() - 16) / 2) + 'px',
cls: me.showHideButtonIconCls,
'data-qtip': (me.renderHidden ? me.showHideButtonTooltipDo : me.showHideButtonTooltipUndo)
}));
me.showHideEl.on('click', function() {
me.setVisible(!me.isVisible());
me.showHideEl.set({
'data-qtip': (!me.isVisible() ? me.showHideButtonTooltipDo : me.showHideButtonTooltipUndo)
});
});
}


if (column && me.showClearAllButton && me.columns.getCount()) {
var column = me.actionColumn || me.extraColumn;
var buttonEl = column.el.first().first();
me.clearAllEl = Ext.get(Ext.core.DomHelper.append(buttonEl, {
tag: 'div',
style: 'position: absolute; width: 16px; height: 16px; top: 25px; cursor: pointer; left: ' + parseInt((column.el.getWidth() - 16) / 2) + 'px',
cls: me.clearAllButtonIconCls,
'data-qtip': me.clearAllButtonTooltip
}));


me.clearAllEl.hide();
me.clearAllEl.on('click', function() {
me.clearFilters();
});
}
},


// private
showInitialFilters: function() {
var me = this;


Ext.each(me.filterArray, function(filter) {
var column = me.columns.get(filter.property);
var field = me.fields.get(filter.property);
if(!column.getEl().hasCls(me.columnFilteredCls)) {
column.getEl().addCls(me.columnFilteredCls);
}
field.suspendEvents();
field.setValue(filter.value);
field.resumeEvents();
});


if (me.filterArray.length && me.showClearAllButton) {
me.clearAllEl.show({duration: 1000});
}
},


// private
resizeContainer: function(headerCt, col) {
var me = this;
var dataIndex = col.dataIndex;


if (!dataIndex) return;
var item = me.containers.get(dataIndex);
if (item && item.rendered) {
var itemWidth = item.getWidth();
var colWidth = me.columns.get(dataIndex).getWidth();
if (itemWidth != colWidth) {
item.setWidth(me.columns.get(dataIndex).getWidth());
item.doLayout();
}
}
},




// private
applyFilters: function(field) {
if (!field.isValid()) return;
var me = this,
grid = me.grid,
column = me.columns.get(field.dataIndex),
newVal = (grid.store.remoteFilter ? field.getSubmitValue() : field.getValue());


if (Ext.isArray(newVal) && newVal.length == 0) {
newVal = '';
}
var myIndex = -1;
Ext.each(me.filterArray, function(item2, index, allItems) {
if(item2.property === column.dataIndex) {
myIndex = index;
}
});
if(myIndex != -1) {
me.filterArray.splice(myIndex, 1);
}
if(!Ext.isEmpty(newVal)) {
if (!grid.store.remoteFilter) {
var filterFn;
switch(column.filter.operator) {
case 'eq':
filterFn = function(item) {
if (column.filter.type == 'date') {
return Ext.Date.clearTime(item.get(column.dataIndex), true).getTime() == Ext.Date.clearTime(newVal, true).getTime();
} else {
return (Ext.isEmpty(item.get(column.dataIndex)) ? me.autoStoresNullValue : item.get(column.dataIndex)) == (Ext.isEmpty(newVal) ? me.autoStoresNullValue : newVal);
}
};
break;
case 'like':
filterFn = function(item) {
var re = new RegExp(newVal, 'i');
return re.test(item.get(column.dataIndex));
};
break;
case 'in':
filterFn = function(item) {
var re = new RegExp('^' + newVal.join('|') + '$', 'i');
return re.test((Ext.isEmpty(item.get(column.dataIndex)) ? me.autoStoresNullValue : item.get(column.dataIndex)));
};
break;
}
me.filterArray.push(Ext.create('Ext.util.Filter', {
property: column.dataIndex,
filterFn: filterFn,
me: me
}));
} else {
me.filterArray.push(Ext.create('Ext.util.Filter', {
property: column.dataIndex,
value: newVal,
type: column.filter.type,
operator: column.filter.operator
}));
}
if(!column.getEl().hasCls(me.columnFilteredCls)) {
column.getEl().addCls(me.columnFilteredCls);
}
} else {
if(column.getEl().hasCls(me.columnFilteredCls)) {
column.getEl().removeCls(me.columnFilteredCls);
}
}
grid.store.currentPage = 1;
if(me.filterArray.length > 0) {
if (!grid.store.remoteFilter) grid.store.clearFilter();
grid.store.filters.clear();
grid.store.filter(me.filterArray);
if (me.clearAllEl) {
me.clearAllEl.show({duration: 1000});
}
} else {
grid.store.clearFilter();
if (me.clearAllEl) {
me.clearAllEl.hide({duration: 1000});
}
}
if (!grid.store.remoteFilter && me.autoUpdateAutoStores) {
me.fillAutoStores();
}
me.fireEvent('filterupdated', me.filterArray);
},


// private
applyDelayedFilters: function(field) {
if (!field.isValid()) return;
var me = this;


me.task.delay(me.updateBuffer, me.applyFilters, me, [field]);
},


// private
applyInstantFilters: function(field) {
if (!field.isValid()) return;
var me = this;


me.task.delay(0, me.applyFilters, me, [field]);
},


//private
getFirstField: function() {
var me = this,
field = undefined;


Ext.each(me.grid.headerCt.getGridColumns(true), function(col) {
if (col.filter) {
field = me.fields.get(col.dataIndex);
return false;
}
});


return field;
},


//private
focusFirstField: function() {
var me = this;


var field = me.getFirstField();


if (field) {
field.focus(false, 200);
}
},


clearFilters: function() {
var me = this;


if (me.filterArray.length == 0) return;
me.filterArray = [];
me.fields.eachKey(function(key, field) {
field.suspendEvents();
field.reset();
field.resumeEvents();
var column = me.columns.get(key);
if(column.getEl().hasCls(Ext.baseCSSPrefix + 'column-filtered')) {
column.getEl().removeCls(Ext.baseCSSPrefix + 'column-filtered');
}
}, me);
me.grid.store.clearFilter();
if (me.clearAllEl) {
me.clearAllEl.hide({duration: 1000});
}


me.fireEvent('filterupdated', me.filterArray);
},


isVisible: function() {
var me = this;


return me.visible;
},


setVisible: function(visible) {
var me = this;


me.containers.each(function(item) {
item.setVisible(visible);
});


if (visible) {
me.focusFirstField();
}
me.grid.headerCt.doLayout();
me.visible = visible;
}
});

another_i
30 Aug 2012, 11:11 PM
I want to use filterbar for filtering already filtered (on client) store. How can I do that? For now when I change any filterbar field all filters are cleared and setting up only filterbar's filters. Thanks.

ldonofrio
31 Aug 2012, 4:57 AM
All filters (excepts using filterFn) are parsed and applied by the plugin.


I want to use filterbar for filtering already filtered (on client) store. How can I do that? For now when I change any filterbar field all filters are cleared and setting up only filterbar's filters. Thanks.

another_i
3 Sep 2012, 5:56 AM
All filters (excepts using filterFn) are parsed and applied by the plugin.

Yep. But how can I use filterBar with prefiltered store by filterFn?

And seems exepts using RegExp in store.filter()?
And simple prefiltering too? ) look next message...

another_i
4 Sep 2012, 2:59 AM
So, I have a store with records for example with next filds:

fields : ["id", "parentId", "name"]

I set a filter :


var parId = 123;
var fltr = {
property: "parentId",
value: new RegExp("^(?!"+parId+"$)")
};
store.filter([fltr]);


In grid i have only one filtered column with dataIndex:"name".

Before filtering by using filterBar I have prefiltered store with 10 records.
After that i filter the store by using filterBar and it clear all filters which was setted before (prefilters), and show records passed successfully only filterBar filters.

another_i
4 Sep 2012, 3:53 AM
You add event in init():


grid.addEvents('filterupdated');


And next you call fireEvent from "me" (me == filterBar) twice:

me.fireEvent('filterupdated', me.filterArray); // string 742
me.fireEvent('filterupdated', me.filterArray); // string 826


But must call fireEvent from "grid":

grid.fireEvent('filterupdated', me.filterArray); // string 742
grid.fireEvent('filterupdated', me.filterArray); // string 826


And so listeners must be added for grid.
Please fix it in source.

another_i
4 Sep 2012, 5:13 AM
I solve the trouble with prefiltering by adding prefilters array and next listener to the grid:


//...
prefilters: [{
property: "parentId",
value: 123
}],


listeners: {
filterupdated: function(filters){
var grid = this;
if(grid.prefilters && grid.prefilters.length > 0)
grid.getStore().filter(grid.prefilters);
}
},
//...


You can also add this functionality (prefilters array and run listener function) in filterBar source file where you find it needed. But it didn't solve trouble with filterFn. Thanks.

jordandev
24 Sep 2012, 9:50 AM
Yes, i have that, currently i'm testing the new versión, i'll upload it to market next week.

Regards

Leonardo

Is this getting anywhere? Having the operations in the filters would be awesome.

Thanks,
Jordan

ldonofrio
27 Sep 2012, 6:38 AM
No fully tested but try v1.1 on market https://market.sencha.com/users/68/extensions/95
(https://market.sencha.com/users/68/extensions/95)
Regards,
Leonardo


Is this getting anywhere? Having the operations in the filters would be awesome.

Thanks,
Jordan

another_i
1 Oct 2012, 2:14 AM
ldonofrio, Please fix a bug with fireEvent('filterupdated'), I wrote about it here: http://www.sencha.com/forum/showthread.php?152923-Ext.ux.grid.FilterBar-plugin&p=882212&viewfull=1#post882212

ldonofrio
2 Oct 2012, 7:40 AM
Fixed in my working copy, thanks

ldonofrio, Please fix a bug with fireEvent('filterupdated'), I wrote about it here: http://www.sencha.com/forum/showthread.php?152923-Ext.ux.grid.FilterBar-plugin&p=882212&viewfull=1#post882212

jimmylu98
8 Oct 2012, 9:07 AM
Thank you for this great great plugin and it works very well for my application.

However, I do have a small problem when I warp the grid header with following css: (see the attached pictures).

My question is there any way to vertical align all filter cells to the bottom?

In attached example, the Humidity filter cell is above Temperature and Dew Point filter cells due to grid header wrap, which is not looks good.

Thank you.



.x-column-header-inner, .x-column-header-inner span { white-space:normal !important; }

sole10g
1 Nov 2012, 9:24 AM
Hi!.
I´m using your plugin like example to deploy a functionality that I need.
Your plugin had been very usefull for me.

I'm trying to create the filterBar before header line, instead of after, but I couldn't find the way to do it. I suppose that I should modify the 'renderFilterBar' method...but I don't know how. Any clue?

Thank you for you help.

EDIT:
I could render the container before the header, but the element inside the container doesn't be shown.
Here is my code:


var textBox = Ext.create('Ext.form.field.Text',{
id: column.id+'-headerTextBox',
emptyText: 'Value',
flex: 1,
margin: 2,
fieldStyle: 'border-left-width: 0px; border-bottom-width: 0px;',
listConfig: listConfig
});

var lockButton = Ext.create('SDMSweb.view.data.LockButton', {
id: column.id+'-headerButton',
handler: function() {
alert('You clicked the button!')
},
margin: 2,
listConfig: listConfig
});
var container = Ext.create('Ext.container.Container', {
id: column.id+'-headerContainerEl',
dataIndex: key,
layout: 'hbox',
style: 'height: 40px; background-color: #749A00;',
width: column.getWidth(),
items: [textBox, lockButton],
listeners: {
scope: me,
element: 'el'
}
});


var dh = Ext.DomHelper;
dh.insertBefore(column.id+'-titleEl', container);


Any clue...?. Thank you!

predator
1 Nov 2012, 10:25 AM
Hi again,

and once again great pluggin.. in fact it is the greatest :)

Can somebody tells me how the operators are configured per column, it appears to be that they are based on the type of filter that is set, but what if one want lets say only equal and not equal for specific column.

Is this handled somehow in the current code?

/Thanks

another_i
1 Nov 2012, 11:24 PM
It seems this functionality isn't realised for now: you can't set filter for a column like a "property equal A and not equal B".

mpete
12 Nov 2012, 6:19 AM
Hi !

First of all, excellent plugin. Really nice !

Then to my feature requests (which may allready be possible ??)..

1. Be able to specify the width for the "dropdown" box when using filter: 'list' of filter: 'combo'
The field can e.g be 150px wide, but I'd like the "dropdown" box to be 300px wide..

2. Only filter data visible in the view.
It seems to me that when adding a new filter, the whole recordset is filtered.
For example I load a view with 1000 rows (records). I then apply 1 column filter.
Now the view is filtered and is displaying 150 records. If, I now apply a new filter to another column, it uses the same time in seconds to apply that filter. In theory it should now only need to filter the 150 records.

A similar scenario can be seen when sorting a column client side. If I have 1000 records visible in my view, it takes about 5 seconds to sort. If now apply 1 column filter (as above), I end up with 150 records in my view. If I now click on the column header to sort, it's much faster. Less than a second.
Seems to be it only sorts what's visible..

3. When using filter: 'list', it would be nice to have checkboxes to the left indicating to the user that multiple values can be selected + that the "dropdown" box disappeared when mouse cursor is not over it anymore.. When using filter: 'combo', it would be nice if the "drowdown" box disappeared when clicking on a value..

Again, great plugin ! Keep up the good work !
Thanks !

regards,
Petter

ldonofrio
12 Nov 2012, 6:33 AM
Thanks Peter,
1) You can do it using ListConfig config of Ext.form.field.Combobox
don't use filter: 'list', instead use filter: {type: 'list', listConfig: {width: 500}} on something like that

2) Yes, entire snapshot is refiltered in client side, if you use server side filtering you can do your own login to speed up the process.

3) I've my js/css override to show checkboxes in a multiSelect combobox, this way this plugin does not depends on another ux component, let me know if you want it.

Regards

Leonardo


Hi !

First of all, excellent plugin. Really nice !

Then to my feature requests (which may allready be possible ??)..

1. Be able to specify the width for the "dropdown" box when using filter: 'list' of filter: 'combo'
The field can e.g be 150px wide, but I'd like the "dropdown" box to be 300px wide..

2. Only filter data visible in the view.
It seems to me that when adding a new filter, the whole recordset is filtered.
For example I load a view with 1000 rows (records). I then apply 1 column filter.
Now the view is filtered and is displaying 150 records. If, I now apply a new filter to another column, it uses the same time in seconds to apply that filter. In theory it should now only need to filter the 150 records.

A similar scenario can be seen when sorting a column client side. If I have 1000 records visible in my view, it takes about 5 seconds to sort. If now apply 1 column filter (as above), I end up with 150 records in my view. If I now click on the column header to sort, it's much faster. Less than a second.
Seems to be it only sorts what's visible..

3. When using filter: 'list', it would be nice to have checkboxes to the left indicating to the user that multiple values can be selected + that the "dropdown" box disappeared when mouse cursor is not over it anymore.. When using filter: 'combo', it would be nice if the "drowdown" box disappeared when clicking on a value..

Again, great plugin ! Keep up the good work !
Thanks !

regards,
Petter

mpete
12 Nov 2012, 1:10 PM
Hi Leonardo,

Thanks a lot for your quick response :)

1. I will try out the listConfig parameter.

2. I understand that the entire recordset is refiltered. Would it be much work (possible ?) to modify the code to only filter the rendered/visible records in the view ? Is seems to me that client side sorting is implemented this way (?)

3. Yes, I would very much like to have your js/css overrides to enable checkboxes in a multiSelect combobox :)

Thanks a lot for your help !

best regards,
Petter Kjeilen

predator
12 Nov 2012, 1:39 PM
If i may suggest to apply delay for the select event on the list filters, as it is currently set as instant and does not gives the user a chance to set multi choice.



select: me.applyDelayedFilters, //original select: me.applyInstantFilters,

mpete
13 Nov 2012, 12:40 AM
Hi Leonardo,

I tried using filter: {type: 'list', listConfig: {width: 500}} , but I cannot see any difference in the rendered combobox. The "dropdown" box/list is still the same width as the field.
I was expecting the "dropdown" box/list to be wider than the field it self..
I might be doing this the wrong way ?

Image:
39995



Here's my code:


// create the Grid
var grid = Ext.create('Ext.grid.Panel', {
store: store,
plugins: [{
ptype: 'filterbar',
renderHidden: false,
showShowHideButton: true,
showClearAllButton: true
}],
columns: {
plugins: [{
ptype: 'gridautoresizer'
}],
items: [{
text : 'Nr.',
widht : 40,
dataIndex : '$MeldNr',
filter : {
type: 'int',
minValue: 1
}
},
{
text : 'Bestiller',
flex : 0.5,
dataIndex: '$KundeNavn',
filter: {type: 'list', listConfig: {width: 500}}
},
{
text : 'Ansvarlig',
flex : 0.5,
dataIndex: '$Ansvarlig',
filter: {type: 'list', listConfig: {width: 500}}
},
{
text : 'Leveranseansvarlig',
flex : 0.5,
dataIndex: '$Leveranseansvarlig',
filter: {type: 'list', listConfig: {width: 500}}
},
{
xtype: 'actioncolumnpro',
items: [{
iconCls: 'domino',
tooltip: 'Open in Notes client',
handler : function(grid, rowIndex, colIndex) {
var rec = store.getAt(rowIndex);
var docunid = rec.get('@unid');
window.open(notesurl+docunid, '_blank');
}
}]
}
],
},
dockedItems: [{
dock: 'top',
xtype: 'toolbar',
items: [{
iconCls: 'add',
text: 'Ny oppgave',
disabled: false,
handler : function() {
//alert('coming soon..');
Ext.MessageBox.show({
title: 'Info',
msg: 'Scheduled for next version...',
buttons: Ext.MessageBox.OK,
icon: Ext.MessageBox.INFO
});
}
},'->', {
xtype: 'component',
itemId: 'status',
tpl: 'Displaying {count} tasks',
style: 'margin-right:5px'
},'->',{
iconCls: '',
text: currentuser,
disabled: true
}]
}],
features: [groupingFeature],
title: "<a style='cursor:pointer;' href='Notes://DSNotes1/C12572B40034A57D/'><img src='Logo.png'/></a>",
viewConfig: {
stripeRows: true,
loadingText: gridLoadingText
}
});


Thanks for your help !

regards,
Petter Kjeilen

ldonofrio
13 Nov 2012, 4:28 AM
Predator,

I'll look into that


If i may suggest to apply delay for the select event on the list filters, as it is currently set as instant and does not gives the user a chance to set multi choice.



select: me.applyDelayedFilters, //original select: me.applyInstantFilters,

ldonofrio
13 Nov 2012, 4:32 AM
Petter,
You've to use matchFieldWidth: false (defaults to true) check the docs http://docs.sencha.com/ext-js/4-1/#!/api/Ext.form.field.Picker-cfg-matchFieldWidth

And for multiSelect checkbox combo use this
js override


// change list base css classes to support checkbox in multiSelect: true
Ext.define('Ext.override.form.field.ComboBox', {
override: 'Ext.form.field.ComboBox',
constructor: function(config) {
if (Ext.isDefined(config.multiSelect)) {
if (config.multiSelect) {
if (!Ext.isObject(config.listConfig)) config.listConfig = {};
config.listConfig.baseCls = Ext.baseCSSPrefix + 'checkboundlist';
config.listConfig.itemCls = Ext.baseCSSPrefix + 'checkboundlist-item';
}
}
this.callParent([config]);
}
});


sass override


// multiSelect combos
$tmpprefix: $prefix;
$prefix: 'x-check';
@include extjs-boundlist;
.#{$prefix}boundlist-item {
padding: 2px;
padding-left: 18px;
background-image: theme-image($theme-name, $menu-icon-unchecked);
background-repeat: no-repeat;
}


.#{$prefix}boundlist-selected {
background-image: theme-image($theme-name, $menu-icon-checked);
background-repeat: no-repeat;
}
$prefix: $tmpprefix;

ldonofrio
13 Nov 2012, 4:45 AM
I've changed that in my working copy only for multiSelect:true combo filters.
Thanks

For now you can use this to patch the plugin:


select: function(txt) {
if (txt.multiSelect) {
me.applyDelayedFilters(txt);
} else {
me.applyInstantFilters(txt);
}
},



If i may suggest to apply delay for the select event on the list filters, as it is currently set as instant and does not gives the user a chance to set multi choice.



select: me.applyDelayedFilters, //original select: me.applyInstantFilters,

mpete
19 Nov 2012, 12:43 PM
Hi Leonardo,

Thanks, that worked out very well :)

Now I have a few new questions..

First, I´ve implemented remote sorting and filtering on my store because it took to long to filter 3000 records locally. remoteFilter is now set to true.
But, then I experience that alle the combos and lists are no longer populated with values.
Do I also have to build the values for these fields on the server now ? Or is that an option ?
If, I have to build the list of values on the server, how do I config my extjs code to do this ?

Second, when filtering a date field I can choose like, greater than, smaller than, unlike for comparison. But, I can only choose 1 type of comparison at 1 time. Is is e.g possible to filter a datefield with date greater than + date smaller than ?
Same for a number field.

Thanks again for your help :)

regards,
Petter

ldonofrio
19 Nov 2012, 12:55 PM
Petter,
1) For 3000 records i think you need server paging, and this way have no sense to build the lists in the client because you doesn't have all posible values, so you have to do it in the server side, look at the code for "autoStoresRemoteProperty" config option, it defaults to "autoStores" so you have to include that key with the arrays in the server response.
Take a look at "fillAutoStores" private method that build the stores based on that property in the response.
Also "autoStoresRemoteProperty" is used in the request to notify the server what fields you need to collect unique values.

2) No there is no way, i've no implemented number/date ranges

Regards
Leonardo


Hi Leonardo,

Thanks, that worked out very well :)

Now I have a few new questions..

First, I´ve implemented remote sorting and filtering on my store because it took to long to filter 3000 records locally. remoteFilter is now set to true.
But, then I experience that alle the combos and lists are no longer populated with values.
Do I also have to build the values for these fields on the server now ? Or is that an option ?
If, I have to build the list of values on the server, how do I config my extjs code to do this ?

Second, when filtering a date field I can choose like, greater than, smaller than, unlike for comparison. But, I can only choose 1 type of comparison at 1 time. Is is e.g possible to filter a datefield with date greater than + date smaller than ?
Same for a number field.

Thanks again for your help :)

regards,
Petter

reweiner
21 Nov 2012, 5:59 AM
Hi Leonardo,

Thanks for the great work.

I think I might have found a problem.

I'm using 'reconfigure' in my grid. One grid I want to have the FilterBar and another one I don't. So I setup 'filter: true' in the columns I want.

Then it renders the filter with no FilterBar -> OK
When I fire the reconfigure event for the new columns with the FilterBar it 'crashes' on function 'renderFilterBar' (around line 530):



var container = Ext.create('Ext.container.Container',
{
dataIndex: key,
layout: 'hbox',
bodyStyle: 'background-color: "transparent";',
---> width: column.getWidth(),
items: [field],
listeners: {
scope: me,
element: 'el',
mousedown: function(e) { e.stopPropagation(); },
click: function(e) { e.stopPropagation(); },
dblclick: function(e) { e.stopPropagation(); },
keydown: function(e) { e.stopPropagation(); },
keypress: function(e) { e.stopPropagation(); },
keyup: function(e) { e.stopPropagation(); }
}
});

I don't know exactly why but I believe is due to the FilterBar has not been displayed yet.

Thanks
R.

gayathr
23 Nov 2012, 2:09 AM
Great Plugin .It helps me a lot :) Thanks a lot

alessiom
29 Nov 2012, 1:15 AM
Hi all.
Thank you very much for the plugin! It is exactly what we were looking for.
I have implemented date and number ranges.
Here is the diff

--- FilterBarOriginal.js 2012-11-29 09:22:14.000000000 +0100
+++ FilterBar.js 2012-11-29 09:45:57.000000000 +0100
@@ -542,13 +542,43 @@
},
plugins: plugins
}));
+ if (column.range && ((column.filter.xtype == 'datefield') || (column.filter.xtype == 'numberfield'))) {
+ var field2 = Ext.widget(column.filter.xtype, Ext.apply(column.filter, {
+ dataIndex: key,
+ flex: 1,
+ margin: 0,
+ fieldStyle: 'border-left-width: 0px; border-bottom-width: 0px;',
+ listConfig: listConfig,
+ preventMark: true,
+ msgTarget: 'none',
+ checkChangeBuffer: 50,
+ enableKeyEvents: true,
+ listeners: {
+ change: me.applyDelayedFilters,
+ select: me.applyInstantFilters,
+ keypress: function(txt, e) {
+ if (e.getCharCode() == 13) {
+ e.stopEvent();
+ me.applyInstantFilters(txt);
+ }
+ return false;
+ },
+ scope: me},
+ plugins: plugins
+
+ }));
+ var items = [field, field2];
+ } else {
+ var items = [field];
+ }
me.fields.add(column.dataIndex, field);
+ me.fields.add(column.dataIndex, field2);
var container = Ext.create('Ext.container.Container', {
dataIndex: key,
layout: 'hbox',
bodyStyle: 'background-color: "transparent";',
width: column.getWidth(),
- items: [field],
+ items: items,
listeners: {
scope: me,
element: 'el',
@@ -675,7 +705,7 @@
}
var myIndex = -1;
Ext.each(me.filterArray, function(item2, index, allItems) {
- if(item2.property === column.dataIndex) {
+ if (item2.id === ('filter-' + field.id)) {
myIndex = index;
}
});
@@ -738,12 +768,14 @@
}
me.filterArray.push(Ext.create('Ext.util.Filter', {
property: column.dataIndex,
+ id: 'filter-' + field.id,
filterFn: filterFn,
me: me
}));
} else {
me.filterArray.push(Ext.create('Ext.util.Filter', {
property: column.dataIndex,
+ id: 'filter-' + field.id,
value: newVal,
type: column.filter.type,
operator: (field.operator || column.filter.operator)



To use the range just add a "range: true" option to the column definition and a couple of field will appear under the column header. The appear awful (especially the date fields), but they work. Corrections and suggestions are welcome, of course.

Just a question: could you please explain how to populate lists and combos in case of remote filtering? I have studied the code (and I will continue to), but I did not understood.

Regards.

Alessio

Fioenix
30 Nov 2012, 10:35 PM
I'm sorry. My English isn't good ^^

There is an issue of showing when we use the grid with group-headers:

40484

I referred to http://www.sencha.com/forum/showthread.php?249112-Ext-4.1.x-Ext.ux.grid.xFilterRow. I think that moving the filter containers to a filter bar is a better solution.

I tried editing FilterBar.js by replacing me.containers with the filter bar:

Replaces:

me.containers = Ext.create('Ext.util.MixedCollection');

with:

me.filterBar = Ext.create('Ext.container.Container', { // adds a filter bar to grid id: grid.id + '-filter-bar',
weight: 100,
height: 23,
dock: 'top',
border: true,
baseCls: Ext.baseCSSPrefix + 'grid-header-ct',
style: 'border-top-color: #c5c5c5;',
layout: {
type: 'hbox'
}
});

Replaces:

me.containers.each(function(item) { Ext.destroy(item);
});
me.containers.clear();
me.containers = null;

with:

// Filter bar me.filterBar.removeAll();
me.filterBar = null;

Replaces:

me.containers.clear();

with:

me.filterBar.removeAll();

Replaces:

var container = Ext.create('Ext.container.Container', {

with:

var container = Ext.create('Ext.container.Container', { id: grid.id + '-filter-container-' + column.dataIndex,
baseCls: Ext.baseCSSPrefix + 'column-header',

Replaces:

me.containers.add(column.dataIndex, container);
container.render(Ext.get(column.id));

with:

me.filterBar.add(container); // adds the container to filterBar

Replaces:

var item = me.containers.get(dataIndex);

with:

var item = me.filterBar.getComponent(me.grid.id + '-filter-container-' + dataIndex);

Replaces:

me.containers.each(function(item) { item.setVisible(visible);
});

with:

me.filterBar.setVisible(visible);

This is the result:

40485

mpete
3 Dec 2012, 3:04 PM
Hi Leonardo,

I can't seem to figure out this autoStore thing.. I can see that the autoStores parameter is sent ,for every field with a filter, with the call for the store for the grid..

But how is the response supposed to be structured ?

I managed to get it working in another way, but this requires me to create a store for every combo in my grid manually.. (i have to know the name for the field..)

first I create the store:


//comboStore
var storeCombo = new Ext.data.JsonStore({
proxy: {
type: 'ajax',
url: 'xDbColumn.xsp?field=status',
reader: {
root: 'data',
totalProperty: 'count'
}
},
fields: [{
name: 'id',
type: 'string'
}, {
name: 'name',
type: 'string'
}],
remoteFilter: true,
autoLoad: true
});

Then I set the column store to this store:


{
text : 'Status',
flex : 0.5,
dataIndex: '$Status',
filter: {xtype: 'combobox',type: 'list',store: storeCombo,displayField: 'name',valueField: 'name',}
}

This works, but as you can see, I have to create a store for every combo manually in my code + I have to know the field name in order to send it along as a parameter in proxy url.

I was hoping for a more automatic way of doing this, hence the name autoStore.. I was kind of expecting these stores to be created automatically.

Do you have or know of any example on using remote combo stores in a more "automatic" way ?

Also, when I apply a filter, I get a horizontal scrollbar at the bottom. When all filters are removed, the scrollbar disappair. I'm using the actioncolumnpro action column plugin.

Any infomation would be greatly appreciated :)

Thanks for your help !

regards,
Petter Kjeilen

Fioenix
3 Dec 2012, 8:57 PM
After changing the filter values at high speed, the filter data was missed. It only includes the last field. The phrase "changing at value at high speed" means that I typed in a field and move the cursor to another field before the filter is run.

40541

I fix this problem temporarily by modifying the applyFilters function: scan all fields in me.fields.

applyFilters: function (/*appliedField*/) {
var me = this,
grid = me.grid;
me.filterArray = [];
me.fields.each(function(field) {
if (!field.isValid()) return;
var column = me.columns.get(field.dataIndex),
newVal = (grid.store.remoteFilter ? field.getSubmitValue() : field.getValue());...

However, it is not good in terms of performance. I would appreciate if you can suggest me any better solution. If you can, please help me.

jimmylu98
25 Jan 2013, 11:06 AM
Fioenix,

I follow your steps ( http://www.sencha.com/forum/showthread.php?152923-Ext.ux.grid.FilterBar-plugin&p=917075&viewfull=1#post917075 )
to make changes, but at the end the FilterBar is disappeared(see attached file). It must something is not correct. Could you please post your modified FilterBar.js as well as any related changed file. I am looking for the this for long time. Thank you for the help.

jimmylu98
25 Jan 2013, 1:33 PM
Fioenix,

Looks like in your steps ( http://www.sencha.com/forum/showthre...l=1#post917075 (http://www.sencha.com/forum/showthread.php?152923-Ext.ux.grid.FilterBar-plugin&p=917075&viewfull=1#post917075) ) missing:


grid.addDocked( me.filterBar );


Two possible issues could come up:
(1) If one or more column filters are false, then filterBar fields will not align with header column. (see attached picture, here company name filter is false). May need add unfilterable column to me.filterBar.

(2) If one dataIndex used in two column, one filter is true, and the other filter is false, the results will both are filterable, since id: grid.id + '-filter-container-' + column.dataIndex. May need column index into id.

langles
28 Jan 2013, 2:09 PM
I had a problem where parentheses appearing in filter text strings seemed to be ignored for filtering purposes. I discovered that they were being interpreted as regular expression grouping characters. After escaping the filter strings, they worked as expected.

Here's the code I modified inside the FilterBar.applyFilters() function:


case 'like' :
var escapedNewVal;
if (Ext.isArray(newVal)) {
escapedNewVal = newVal.map(Ext.String.escapeRegex);
} else {
escapedNewVal = Ext.String.escapeRegex(newVal);
}
filterFn = function(item) {
var re = new RegExp(escapedNewVal, 'i');
return re.test(item.get(column.dataIndex));
};
break;
case 'in' :
var escapedNewVal;
if (Ext.isArray(newVal)) {
escapedNewVal = newVal.map(Ext.String.escapeRegex);
} else {
escapedNewVal = Ext.String.escapeRegex(newVal);
}
filterFn = function(item) {
var re = new RegExp('^' + escapedNewVal.join('|')
+ '$', 'i');
return re.test((Ext.isEmpty(item
.get(column.dataIndex))
? me.autoStoresNullValue
: item.get(column.dataIndex)));
};
break;

KajaSheen
30 Jan 2013, 6:13 AM
Hey,

very nice Plugin. Been playing around with it and noticed two little things:

OperatorButton gives an error, when the filterbar is destroyed before it was rendered. I.e. when part of a hidden tab or maybe even when renderHidden is true. Check if operatorButtonEl is already defined.

onFieldDestroy: function() {
var me = this;

if(Ext.isDefined(me.operatorButtonEl)) {
me.operatorButtonEl.destroy();
}

me.menu.destroy();
},

Second I wanted to change the default operator for my date field to be gte, but the operator icon was still the eq one. Found that plugin OperatorButton does not set the operator (or eq is just assumed). Added the dperator from the column definition.

if (me.enableOperators && (column.filter.type == 'date' || column.filter.type == 'int' || column.filter.type == 'float')) {
plugins.push({
ptype: 'operatorbutton',
operator: column.filter.operator,
listeners: {
operatorchanged: function(txt) {
if (Ext.isEmpty(txt.getValue())) return;
me.applyInstantFilters(txt);
}
}
});
}

wki01
15 Feb 2013, 1:00 AM
Tested with 4.2 RC1

so it works


.....
plugins: [
Ext.create('Ext.grid.plugin.RowEditing', {
clicksToMoveEditor: 1,
autoCancel: false
}), {
ptype: 'filterbar',
renderHidden: false
}]
.....


so it NOT works


.....
plugins: [{
ptype: 'filterbar',
renderHidden: false
},
Ext.create('Ext.grid.plugin.RowEditing', {
clicksToMoveEditor: 1,
autoCancel: false
})
]
.....

The error is (row = 104520):
Type Error: column.getEditor is not a function


thanks

predator
15 Feb 2013, 4:12 AM
} else {
- grid.store.clearFilter();
- if (me.clearAllEl) {
- me.clearAllEl.hide({
- duration: 1000
- });
+ //Added as it was causing the grid always to reload
+ if(grid.store.isFiltered()) {
+ grid.store.clearFilter();
+ if (me.clearAllEl) {
+ me.clearAllEl.hide({
+ duration: 1000
+ });
+ }
}
}

johanhaest
26 Feb 2013, 1:38 AM
Im having a problem that when I press enter in a filterfield, he sorts the column instead of filtering. Doesn't even come in the keypress event.

EDIT:

It's fixed when i uncommented these lines:


keydown: function(e) { e.stopPropagation(); },
keypress: function(e) { e.stopPropagation(); },
keyup: function(e) { e.stopPropagation(); }


Can anybody elaborate this?

damo
5 Mar 2013, 10:58 AM
Excellent plugin!

One problem I'm having at the moment is that combos do not display correctly in IE6, the dropdown fills the whole screen and the clear button on the right of the filters doesn't show either, are these know issues as the market page does state IE6 support.

I've not had chance to debug it yet, thought i'd see if it was a known issue first.

Thanks,
Damo

grpbhb
13 Mar 2013, 4:26 AM
FilterBar + Bufferd Store + Memory Proxy
The FilterBar feature searchs only in the current page not in all pages!
Thankyou.



var store = Ext.create('Ext.data.Store', {
model : 'Mediciones',
remoteSort : false,
remoteFilter : false,
autoDestroy : true,
autoLoad : false,
pageSize : 100,
buffered: true,
proxy : {
type : 'memory',//'pagingmemory',
reader : {
type : 'json',
root : 'list'
}
}
});

ldonofrio
13 Mar 2013, 5:22 AM
in buffered store the store have only the loaded page of records so the plugin can't have access to the entire dataset. Maybe you have to load all pages first.

grpbhb
13 Mar 2013, 9:32 AM
I found the fix. The bug is in the method filter of the Store.
My solution in green.



filter: function(filters, value) {
if (Ext.isString(filters)) {
filters = {
property: filters,
value: value
};
}


var me = this,
decoded = me.decodeFilters(filters),
i = 0,
doLocalSort = me.sorters.length && me.sortOnFilter && !me.remoteSort,
length = decoded.length;


for (; i < length; i++) {
me.filters.replace(decoded[i]);
}


if (me.remoteFilter) {

delete me.totalCount;




if (me.buffered) {
me.pageMap.clear();
me.loadPage(1);
} else {

me.currentPage = 1;

me.load();
}
} else {

if (me.filters.getCount()) {
me.snapshot = me.snapshot || me.data.clone();
if(me.proxy.type != 'pagingmemory'){
me.data = me.data.filter(me.filters.items);
}
else{
var list = new Ext.util.MixedCollection(),
items = Ext.Array.clone(me.proxy.data);
for(i=0;i<items.length;i++){
list.add(Ext.create(me.model,items[i]));
}
me.data = list.filter(me.filters.items);
}
if (doLocalSort) {
me.sort();
} else {

me.fireEvent('datachanged', me);
me.fireEvent('refresh', me);
}
}
}
},

lelit
15 Mar 2013, 5:29 AM
Trying out this great plugin with the recently released 4.2.0.663, there is compatibility issue: in a few places it calls
me.grid.headerCt.getGridColumns(true), where in previous versions of ExtJS that
true meant refresh the cache.

Current version of that method does not accept the flag anymore, its only arguments are declared private... and thus an error is raised about “result.push() is not a function”, in grid/header/Container.js at line 883.

As a quick fix, simply removing the parameter let me go further in my tests.

ldonofrio
15 Mar 2013, 6:57 AM
thanks lelit, i've noted that too

milestonebass
18 Mar 2013, 10:11 PM
When setting a column width, the filterbar field for that column is not being initially rendered. However, flexes work fine.

Has anyone else experienced this problem (and got a possible solution/explanation)?


plugins: [{
ptype: 'filterbar',
renderHidden: false,
showShowHideButton: true,
showClearAllButton: true
}],



{
xtype: 'gridcolumn',
dataIndex: 'name',
width: 200,
text: 'Role',
filter: true
},

Behavior:
The filter bar is initially hidden when the grid's backing store is loading (ajax load). Once loaded, the filterbar shows and the filters on columns with specified widths are not rendered. A hide, then show (using the show/hide icon) renders the fields correctly.

mrsunshine
19 Mar 2013, 12:54 AM
@lelit (http://www.sencha.com/forum/member.php?530532-lelit): thanks for sharing this, saved me some time ;-)

wki01
21 Mar 2013, 12:53 AM
Trying out this great plugin with the recently released 4.2.0.663, there is compatibility issue: in a few places it calls
me.grid.headerCt.getGridColumns(true), where in previous versions of ExtJS that
true meant refresh the cache.

Current version of that method does not accept the flag anymore, its only arguments are declared private... and thus an error is raised about “result.push() is not a function”, in grid/header/Container.js at line 883.

As a quick fix, simply removing the parameter let me go further in my tests.

I replaced



me.grid.headerCt.getGridColumns(true)


with



me.grid.headerCt.getGridColumns()


but I always get result.push () is not a function
I do something wrong?

thanks

mrsunshine
21 Mar 2013, 1:22 AM
Search the file also for just


.getGridColumns(true)
than you should find one more and it should work

cwtuan
24 Mar 2013, 10:06 PM
any update for ExtJS 4.2?
Thanks!

jordandev
9 Apr 2013, 8:06 AM
renderExtraColumn seems to fail sometimes after reconfigure is called on the grid 4.2 now. It creates the header fine but the first column is missing so all the columns are shifted one over. If I scroll up and down it fixes itself.

This is with a buffered grid.

Anyone else get this?

Steve88
11 Apr 2013, 1:55 AM
There is a little bug with date filter.
If you have null/empty date value in the store, during the application of the filter an error will occur:
"Uncaught TypeError: Cannot call method 'getTime' of null"

This can be easily corrected adding a if control before the applyFilters method (FilterBar.js, 666 row) return the item.



switch(operator) {
case 'eq':
filterFn = function(item) {
if (column.filter.type == 'date') {
var valore = item.get(column.dataIndex);
if(valore && valore !== null && valore != "") return Ext.Date.clearTime(item.get(column.dataIndex), true).getTime() == Ext.Date.clearTime(newVal, true).getTime();
} else {
return (Ext.isEmpty(item.get(column.dataIndex)) ? me.autoStoresNullValue : item.get(column.dataIndex)) == (Ext.isEmpty(newVal) ? me.autoStoresNullValue : newVal);
}
};
break;


Repeated of course for all operators. :)

Steve

hansl1963
13 Apr 2013, 5:02 AM
Hello,

I'm using FilterBar successfully with Ext 4.1.3 but after upgrading to 4.2.0663 I get an error when loading the grid.

This is a part of the code im using:


Ext.define('sdmDataGridPanel', {
extend: 'Ext.grid.Panel',

forceFit: true,
store: Ext.create('sdmDataStore'),

plugins: [{
ptype: 'filterbar',
showShowHideButton: false,
showClearAllButton: false
}],

id: 'grid',

....

And get the next error:

TypeError: result.push is not a function



result.push(item);



xt-all-debug.js (row 107050)

Hope somebody can help me..

lelit
15 Apr 2013, 3:45 AM
That's probably the same problem reported in the message #134 in this thread (look at the previous page): you probably need to tweak a few lines in the source where there is a call to the function getGridColumns(true): simply remove the argument and it should work.

hansl1963
17 Apr 2013, 3:44 AM
Thanks lelit,

I have been blind i think...
Going to tweak the files...

It works...

landoni
18 Apr 2013, 5:44 AM
Thanks for this plugin, it's just what i was looking for.

I have a similar problem as mpete, i can´t populate my comboboxes when the grid store is set to "remoteFilter: true". Should i create a separate store for each combo? I'm just getting started in extjs 4, any example would be appreciated.

Thanks in advance,

Agustin

langles
10 May 2013, 4:45 PM
I had an issue where there was a filter applied to my grid store on a column that is not displayed in the grid. The FilterBar plugin was ignoring this initial filter because of this line in the parseInitialFilters() function:

if (filter.property && !Ext4.isEmpty(filter.value) && me.columns.get(filter.property)) {

My fix was to add this inital filter to the me.filterArray even though it didn't satisfy the condition:

me.columns.get(filter.property)

Regards,

Scott Langley
slangley@scharp.org

hschaefer123
23 Jun 2013, 5:04 AM
Thanks for the great pluging!

I am currently migrating from Ext 3.4 to 4.2.x and have to reimplement my CustomFilterBar needs.

I took this as the new foundation of my GridFilter.

Here are some comments on Bugs / things i needed to implement!

1) Render bug on using "renderHidden: false"

You have to replace afterender event by viewready
//grid.on('afterrender', me.renderFilterBar, me, { single: true });
grid.on('viewready', me.renderFilterBar, me, { single: true });

this should solve the problem with hidden columns and filters initially shown

2) applyFilters
i disabled delay for filters triggered by RETURN Key (also for remote loading).
Formerly i do not used change event, but this way it works quite well.
I think delaying during typing is ok, but you do not want to wait using RETURN KEY

//applyFilters: function(field, newVal) {
applyFilters: function(field, newVal, oldValue, eOpts) {

...
var delay = (!eOpts) ? 10 : me.updateBuffer;
//me.task.delay(me.updateBuffer, function() {
me.task.delay(delay, function() {

3) Info's / debud output on things that corrupts MixedCollections on duplicate keys:
parseFiltersConfig:...
generally i changed the default behavior that each column will have a autoFilter.
If i do not want a column filtered, i have to add filter: false.
Using Sencha Architect this is more comfortabel, because i do not have to add a custom config property for each column!



...
Ext.each(columns, function(column) {
if (column.filter || column.dataIndex && column.filter !== false) {
if (!column.filter || column.filter === true || column.filter === 'auto') { // automatic types configuration (store based)
var modelField = me.grid.store.model.prototype.fields.get(column.dataIndex);
//var type = me.grid.store.model.prototype.fields.get(column.dataIndex).type.type;
if (modelField) {
var type = modelField.type.type;
if (type == 'auto') type = 'string';
column.filter = type;
} else {
column.filter = 'string';
console.log('Grid FilterBar warning! invalid dataIndex "' + column.dataIndex + '" for column "' + column.text + '"');
}
}




I also added warnings for missing column.DataIndex

At the end i added code for checking on duplicate keys and log a warning


if (!me.columns.containsKey(column.dataIndex))
me.columns.add(column.dataIndex, column);
else
console.log('Grid FilterBar warning! Duplicate dataIndex "' + column.dataIndex + '" for column "' + column.text + '"');



I also added lot's of things around using glyphs / pictos from FontAwesome and so on to have a nice UI, but the interesting things for the common are mentioned above!

You also have add the things mentioned formerly in this thread like
- use getGridColumns() instead getGridColumns(true)

Maybe this is a little timesave for you.

Cheers Holger

lelit
23 Jun 2013, 1:07 PM
Leonardo, any chance of putting a version of the plugin on some public versionated site, such as github or bitbucket, where contributions like Holger's, and in general simple fixes, would be simpler to track?

anirudh.chhabra
29 Jun 2013, 3:41 PM
Hi,

First of all, absolutely great plugin. Great job !

I am trying to use this plugin - works well for me in normal scenario, but I run into some issues with certain scenarios.

I am using Ext JS version 4.2.1 (already changed getGridColumns(true) to getGridColumns(). Now, here is the scenario:

1. It works well if I try to reconfigure the grid without any locked columns
2. To handle columns, I have defined following in my grid config:


normalGridConfig: {
plugins: [{
ptype: 'filterbar',
renderHidden: false,
showShowHideButton: true,
showClearAllButton: true
}]
},
lockedGridConfig: {
plugins: [{
ptype: 'filterbar',
renderHidden: false,
showShowHideButton: true,
showClearAllButton: true
}]
},


This works fine for the first time ie when the grid is not reconfigured yet.

Once I reconfigure the grid, I get the following error:
this.grid.headerCt.getColumns is undefined

I just tried to update all references of
headerCt.getColumns with


var headerCt = this.grid.headerCt?this.grid.headerCt:this.grid.normalGrid.headerCt?this.grid.normalGrid.headerCt:this.grid.lockedGrid.headerCt; var columns = headerCt.getGridColumns();

Not sure if that's teh correct way, but at least I didn't get the headerCt error. But when I reconfigure the grid, I do not see the grid filters.

Will really appreciate your help on this one.

Thanks,
Ani

landoni
7 Aug 2013, 5:15 AM
Hi, is it possible to search between dates? thanks!

hschaefer123
9 Aug 2013, 2:01 AM
The default filter fields uses the comparator "eq" for equals or "like" depending on datatype.

For this we use addtional comparators like
lt = lowerThan
gt = greaterThan
le = lowerEquals
ge = greaterEquals
...

This way you can have one filter field GE and another column for LE,
but you need two columns.
For ext 3.x i have implemented a DataRangeWidget to be able to select rangeswith such a widget
but it is currently not migrated to 4.2.x

Currently the shown implementation of filter does not allow dataIndex twice, means used column dataIndex has to be unique (because of the used MixedCollections and taking dataIndex as KEY!).

So there is currently no easy support for your request!

Cheers Holger

landoni
9 Aug 2013, 6:55 AM
thanks for the reply, guess i'll have to make a search form then, 2 columns will not work. Thanks again

m0r14rty
26 Aug 2013, 7:50 AM
I wanted to note that in 4.2, the interceptor for column.setPadding() doesn't work anymore as it's no longer a function within Ext.grid.column.Column. I've written another thread in Q&A asking what happened to this function so it's possible to find out which function to intercept and avoid now.

I'm getting all my column and field data for my store from metaData in the call, so it might still work with grids that are already defined. It seems that some of them work while others don't, ex: if there is no text then they render the boxes correctly.

http://www.sencha.com/forum/showthread.php?270734-setPadding-method-in-Ext.grid.column.Column-removed-in-4.2

joenilson
6 Sep 2013, 5:48 AM
Hi, where must to be the "grid.addDocked( me.filterBar );" code, i will appreciate your answer or the filterBar.js updated file.

joenilson
9 Sep 2013, 8:46 AM
Hi, i do a modification to this extension and make that this render docked and the operatorbutton can use languages for multilang apps, i attached a working example with extjs 4.2.0,

All comments are welcome.

2013-09-11: I updated the uxs.css and the FilterBar.js because with a selModel checkbox active it was rendering not aligned with the columns.

ajaxvador
9 Sep 2013, 12:45 PM
+1

JavascriptParrot
18 Sep 2013, 5:48 AM
I try this with Ext 4.2.1 but is doesn't work



Uncaught TypeError: Object #<error> has no method 'push' ext-all-debug.js:109366

Update:
The updated version from joenilson (http://www.sencha.com/forum/member.php?22322-joenilson) throws the same error.

BillySao
19 Sep 2013, 1:07 PM
hello, I'm working on sencha architect Version: 2.2.2 Build: 991, my problem is that when I give focus to the header which has a built textField and start writing an entry in the filter to me starts to filter it loses focus and the data you enter.

45908


45906
45907

dr_d00m
20 Sep 2013, 2:47 AM
Hi.
I would like to add some custom elements to the FilterBar (images in a div in my case) to the FilterBar, if the filter is disabled for a column.
Is that somehow possible?
Thanks in advance.

joenilson
25 Sep 2013, 8:32 AM
I try this with Ext 4.2.1 but is doesn't work



Uncaught TypeError: Object #<error> has no method 'push' ext-all-debug.js:109366

Update:
The updated version from joenilson (http://www.sencha.com/forum/member.php?22322-joenilson) throws the same error.

Can you send some code to reproduce the problem?.

thanks

Sundarganesh Ramar
4 Oct 2013, 4:07 AM
Hi,
First of all thank you for the nice plugin.but i am facing some problem when i implement thus plugin.Anyone can guide me plz?
i am not using layout:fit,so when i scroll the page headers are also scrolling but Filters are in the same position so i am getting some confusion.is there anyway to move filter along with grid headers.


Advance Thanks

HybrideRD3
7 Oct 2013, 3:31 PM
If there is already a Git Repo, let me know... Thanks

langles
11 Oct 2013, 10:11 AM
The breakage I found going from Ext JS 4.1.x to 4.2.x is due to the method:

Ext.grid.header.Container.getGridColumns()

changing substantially in its implementation:

http://docs.sencha.com/extjs/4.1.0/source/Container3.html#Ext-grid-header-Container-method-getGridColumns

http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.grid.header.Container-method-getGridColumns

My work around was to add a new method to FilterBar.js that essentially mimics the old functionality of the Ext.grid.header.Container.getGridColumns() method:


getGridColumns : function(refreshCache) {
var me = this, gridHeaderContainer = this.grid.headerCt, result = refreshCache
? null
: gridHeaderContainer.gridDataColumns;
// Not already got the column cache, so collect the base columns
if (!result) {
gridHeaderContainer.gridDataColumns = result = [];
gridHeaderContainer.cascade(function(c) {
if ((c !== gridHeaderContainer) && !c.isGroupHeader) {
result.push(c);
}
});
}
return result;
},

And then wherever FilterBar.js calls:

this.grid.headerCt.getGridColumns(true);

replace that with a call to:

this.getGridColumns(true);

shankar8rajah1
1 Nov 2013, 2:38 PM
was trying to use this plugin and got this error:

TypeError: k.push is not a function

Below is what I have:


var grid = Ext.create('Ext.grid.Panel', { border: false,
region: 'center',
//indexes:['name','service_group','azul_version', 'host_tech','ait_num','app_name','data_center','filer_mounts','instnaces','env'],
store: store,
columns: createHeaders(10),
loadMask: true,
features: [filters,searching],
width: 400,
layout: 'fit',
tbar: Ext.create('Ext.Toolbar'),
bbar: Ext.create('Ext.Toolbar'),
plugins: [{
ptype: 'filterbar',
renderHidden: false,
showShowHideButton: false,
showClearAllButton: false
}],
enableTextSelection : true,
selModel: {
selType: 'cellmodel'
}
});

<link rel="stylesheet" type="text/css" href="/content/js/ext4/resources/css/ext-all.css" />
<script type="text/javascript" src="/content/js/ext4/bootstrap.js"></script>
<!-- Shared --> <link rel="stylesheet" type="text/css" href="/content/js/ext4/examples/shared/example.css" />
<!-- Example --> <link rel="stylesheet" type="text/css" href="/content/js/ext4/examples/ux/grid/css/GridFilters.css" /> <link rel="stylesheet" type="text/css" href="/content/js/ext4/examples/ux/grid/css/RangeMenu.css" /> <link rel="stylesheet" type="text/css" href="/content/js/overrides.css" /> <link rel="stylesheet" type="text/css" href="/content/js/uxs.css" />
<link rel="stylesheet" type="text/css" href="/content/js/app.css" />
<script type="text/javascript" src="/content/js/Ext.ux.grid.HeaderFilters.js"></script>
<script type="text/javascript" src="/content/js/ClearButton.js"></script>
<script type="text/javascript" src="/content/js/OperatorButton.js"></script> <script type="text/javascript" src="/content/js/ActionPro.js"></script>
<script type="text/javascript" src="/content/js/FilterBar.js"></script>
<script type="text/javascript" src="/content/js/Searching.js"></script>

joenilson
15 Nov 2013, 8:40 AM
Hi all, i update the code with the comments from the post
http://www.sencha.com/forum/showthread.php?152923-Ext.ux.grid.FilterBar-plugin&p=1002888&viewfull=1#post1002888

I see a issue when you reconfigure the store in the grid, that do a Registering error, to fix it i use

grid.suspendEvents();
grid.reconfigure(storeModified);
grid.resumeEvents();

And the filterbar renders normally.


Because this a small correction i dont change the version.

Regards,

Joe

cwtuan
15 Nov 2013, 8:54 AM
Thank you, Joe!

sania1313
3 Jan 2014, 6:54 AM
1) Clear button does not appear anymore when you enter filter values;
2) It would sence to clear filters when you hide filter row.

alonron
5 Feb 2014, 4:02 AM
Hello

I'm using the latest filterBar with Extjs 4.2.2.
When I apply the filterBar to a grid that has horizontal scrolling, when I scroll it doesn't effect the filterBar row. The result is that the grid scrolls to the right while the filterBar row stays in a fixed position.

Grid Screenshot 1: Initial view before scrolling.

47818


Grid Screenshot 2: View after scrolling (Look at the filterBar row that is not aligned with the headers)
47819


Thank you for helping!

joenilson
10 Feb 2014, 3:22 PM
Can you provide some code to test.

alonron
10 Feb 2014, 9:25 PM
Thank you.

Even when I just re size the columns in the FilterBarDemo.html, it has the same scrolling problem.
I enlarged the width of some columns:


{
text : '#',
widht : 50,
dataIndex : 'id',
filter : {
type: 'int',
minValue: 1
}
},
{
text : 'Company',
flex : 1,
dataIndex: 'company',
filter: true
},
{
text : 'Price',
width : 700,
renderer : 'usMoney',
dataIndex: 'price',
filter: true
},
{
text : 'Change',
width : 500,
renderer : change,
dataIndex: 'change',
filter: true
},

{
text : '% Change',
width : 75,
renderer : pctChange,
dataIndex: 'pctChange',
filter: true
},
{
xtype : 'datecolumn',
text : 'Last Updated',
width : 500,
format : 'm/d/Y',
dataIndex: 'lastChange',
filter: true
},
{
text : 'Category',
flex : 0.5,
dataIndex: 'category',
filter: 'combo'
},
{
text : 'Country',
flex : 0.5,
dataIndex: 'country',
filter: 'list'
}

Please copy it to the demo and see it happening.

Thank you

byhell
11 Feb 2014, 6:33 AM
Thank you.

Even when I just re size the columns in the FilterBarDemo.html, it has the same scrolling problem.
I enlarged the width of some columns:


{
text : '#',
widht : 50,
dataIndex : 'id',
filter : {
type: 'int',
minValue: 1
}
},
{
text : 'Company',
flex : 1,
dataIndex: 'company',
filter: true
},
{
text : 'Price',
width : 700,
renderer : 'usMoney',
dataIndex: 'price',
filter: true
},
{
text : 'Change',
width : 500,
renderer : change,
dataIndex: 'change',
filter: true
},

{
text : '% Change',
width : 75,
renderer : pctChange,
dataIndex: 'pctChange',
filter: true
},
{
xtype : 'datecolumn',
text : 'Last Updated',
width : 500,
format : 'm/d/Y',
dataIndex: 'lastChange',
filter: true
},
{
text : 'Category',
flex : 0.5,
dataIndex: 'category',
filter: 'combo'
},
{
text : 'Country',
flex : 0.5,
dataIndex: 'country',
filter: 'list'
}

Please copy it to the demo and see it happening.

Thank you

I had the same problem with my grid using this plugin. To solve the problem in the grid i used the parameter:


forceFit: true

and the grid autoadjust and hide the problem. It's not the best solution, but solves the problem for grids with a small number of columns.

Thankyou

alonron
11 Feb 2014, 9:26 PM
Thank you.

My grid has many columns and I have to use scrolling.

Please notice that in the previous version of the FilterBar (last updated at 2012-07-31), this bug doesn't exists. It only exists in the newer version (last updated at 2013-11-15).

Thank you for helping.

Masat0
11 Feb 2014, 10:59 PM
Can you provide some code to test.
I change paths in FilterBarDemo.html

<link rel="stylesheet" type="text/css" href="http://cdn.sencha.com/ext/gpl/4.2.1/resources/css/ext-all.css" />
<script type="text/javascript" src="http://cdn.sencha.com/ext/gpl/4.2.1/ext-all.js"></script>
and
1) Clear button does not appear anymore when you enter filter values;

alonron
17 Feb 2014, 5:21 AM
Hello

I'm using the latest filterBar with Extjs 4.2.2.
When I apply the filterBar to a grid that has horizontal scrolling, when I scroll it doesn't effect the filterBar row. The result is that the grid scrolls to the right while the filterBar row stays in a fixed position.

Grid Screenshot 1: Initial view before scrolling.

47818


Grid Screenshot 2: View after scrolling (Look at the filterBar row that is not aligned with the headers)
47819


Thank you for helping!

Hello again,

The problem is in latest version of the filterbar, when I replaced it with the older one, I didn't get it. I think it's one of the new updates:


* @updated 2013-09-06 by Joe Nilson (joenilson at gmail dot com)
* Changed to docked bar to work with grouped header, using the code from:
* http://www.sencha.com/forum/showthread.php?152923-Ext.ux.grid.FilterBar-plugin&p=917075&viewfull=1#post917075
* @updated 2013-09-11 by Joe Nilson (joenilson at gmail dot com)
* Fixed docked bar to render correctly the checkbox header column in selmodel
* @updated 2013-11-15 by Joe Nilson (joenilson at gmail fot com)
* Applied a fix to rendering the column headers using the code from:
* http://www.sencha.com/forum/showthread.php?152923-Ext.ux.grid.FilterBar-plugin&p=1002888&viewfull=1#post1002888
(http://www.sencha.com/forum/showthread.php?152923-Ext.ux.grid.FilterBar-plugin&p=1002888&viewfull=1#post1002888)

Please help me with this. Thank you

Syndicate
17 Mar 2014, 2:04 AM
What to do if i want to dissable some columns filter (i dont need it on each column), without shifting all filters in row.
I read here that i need to add some emprty container. But how it to do?
filter: false (filter: dissbled)

Syndicate
25 Mar 2014, 12:23 AM
my solution

FilterBar.js


disabledTpl: {
xtype: 'textfield',
disabled: true
},


in grid, coloumn


{
header: getTranslation(94),
dataIndex: 'priority',
align: 'center',
editor: {
xtype: 'numberfield',
maxValue: 10000000000000000,
minValue: 0
},
filter: 'disabled'
},

loiane
25 Mar 2014, 8:28 AM
my solution

FilterBar.js


disabledTpl: {
xtype: 'textfield',
disabled: true
},


in grid, coloumn


{
header: getTranslation(94),
dataIndex: 'priority',
align: 'center',
editor: {
xtype: 'numberfield',
maxValue: 10000000000000000,
minValue: 0
},
filter: 'disabled'
},


Thx!

loiane
25 Mar 2014, 8:52 AM
The column move event was also missing in this plugin.

My solution (the quickest one I came up):

inside init function:


grid.on({
columnresize: me.resizeContainer,
columnhide: me.resizeContainer,
columnshow: me.resizeContainer,
beforedestroy: me.unsetup,
reconfigure: me.resetup,
columnmove: me.columnmove,
scope: me
});


and handler:


columnmove: function(ct, column, fromIdx, toIdx, eOpts){
var me = this;
me.grid.removeDocked( me.filterBar, true );
me.grid.headerCt.remove( me.extraColumn, true );
me.setup(me.grid);
}

loiane
25 Mar 2014, 8:57 AM
Hi,

I took the freedom to put the plugin in github, this way we can all make pull requests and keep the plugin updated. ;)

https://github.com/loiane/Ext.ux.grid.FilterBar

standa.habich
27 Mar 2014, 5:08 AM
button action is "grid.store.clearFilter();" cleared store but filterbar field no cleared.
how reset filterbar with button in toolbar?

and

grid.store.filter({ property: 'cell', value: "search string" });
Only filtering store but no set filterbar field.

how to do it?

Syndicate
27 Mar 2014, 11:01 AM
button action is "grid.store.clearFilter();" cleared store but filterbar field no cleared.
how reset filterbar with button in toolbar?
try this


me.filterBar.clearFilter();

standa.habich
27 Mar 2014, 12:31 PM
thx
correctly is

me.filterBar.clearFilters();

ok, great. And set filterBar?

grid.store.filter({ property: 'id', value: "56"});
is not correctly. This is set only store but after usage filterBar is filter overwrite because filterBar is clear. How to set?

Syndicate
27 Mar 2014, 1:13 PM
Try this.
May be i dont understand what do you want



function setFilterBar (property, value) {
// set here you grid
grid.filterBar.fields.eachKey(function(index, field){
if(index == property) {
field.setValue(value);
}
})
}

setFilterBar('id', 56')

standa.habich
27 Mar 2014, 1:48 PM
its work. thx.

I added



setFilterBar: function(grid, property, value) {
grid.filterBar.fields.eachKey(function(index, field){
if(index == property) {
field.setValue(value);
}
})
},


to FilterBar.js... excelent function

3xc3ption
14 Apr 2014, 4:45 AM
Hi,


first, the plugin is very nice, thanks!!


Now my question: How i bind a jsonstore to send multiquerys to the server?
I want send the queryfield and the queryvalue, but i dont know how ....


I see the filterArray, but how can i use them?:-/


can anybody help me, please

loiane
14 Apr 2014, 8:58 AM
Hi,


first, the plugin is very nice, thanks!!


Now my question: How i bind a jsonstore to send multiquerys to the server?
I want send the queryfield and the queryvalue, but i dont know how ....


I see the filterArray, but how can i use them?:-/


can anybody help me, please

In your store, set remoteFilter: true. If your store is binded to the grid that is using this plugin, it will send the parameters automatically to the server.
Try it and open google developer tools or firebug to see the parameters that are sent.

3xc3ption
15 Apr 2014, 4:14 AM
Hi loiane,

thanks for your the fast answer:.
Now it works!!:))=D>

But i have an other problem with my scrollable grid! How can i scroll the fixbar vertical?:-/

cow_boy
13 May 2014, 2:25 AM
Hi, one of my grid column has dataIndex attribute not in a simple format but in a "fieldX.fieldY" format. So that, in server side first i make a inner join of tableX with tableY and filter results accordingly. But, this filter does not support this notation. Any idea ?

cow_boy
13 May 2014, 11:30 AM
How to make initial filtering ? For example, i want one of my columns to be filtered on grid load.

andrei.neculau
14 May 2014, 3:40 PM
A license clarification would be good to have (to be included in the git repo as well)

Thanks

BillySao
22 May 2014, 7:02 AM
I am working with Extjs plugin V 4.2.2 and version2013-11-15 by Loiane Groner.
I have the following questions:
1 - The header columns are not filtering completely:

49084


2 - At the scroll bar when there are many columns creates a strange and misaligned causing confusion:
49085

3 - The button to clean the filters does not look:

49086

Is there any solution?.

cow_boy
22 May 2014, 7:30 AM
Yes there is a solution but i will not answer.Ha ha ha.

stewardsencha
28 May 2014, 8:05 AM
Really nice plugin. Thank you.
Less mousing than the features filter, and nice to have a visual clue for the current filter.

We can't alll be css cowboys. I too do not have the smarts to figure out #3... the issue with the glass/X icons.

This is my best guess at a fix...



//private
renderButtons: function() {
var me = this;

if (me.showShowHideButton && me.columns.getCount()) {
var column = me.actionColumn || me.extraColumn;
var buttonEl = column.el.first().first();
me.showHideEl = Ext.get(Ext.core.DomHelper.append(buttonEl, {
tag: 'div',
style: 'position: absolute; width: 16px; height: 16px; top: 5px; cursor: pointer; left: ' + parseInt((column.el.getWidth() - 16) / 2) + 'px',
cls: me.showHideButtonIconCls,
'data-qtip': (me.renderHidden ? me.showHideButtonTooltipDo : me.showHideButtonTooltipUndo)
}));
me.showHideEl.on('click', function() {
me.setVisible(!me.isVisible());
me.showHideEl.set({
'data-qtip': (!me.isVisible() ? me.showHideButtonTooltipDo : me.showHideButtonTooltipUndo)
});
});
}

/* dsm 29 apr 14 : Clear (red X) button not shown correctly
Not sure what I am doing here.

a) change top from 25px to 5px for *both* style properties (above and below)
b) add show on click below
c) add hide on click in applyFilters method
*/
if (me.showClearAllButton && me.columns.getCount()) {
var column = me.actionColumn || me.extraColumn;
var buttonEl = column.el.first().first();
me.clearAllEl = Ext.get(Ext.core.DomHelper.append(buttonEl, {
tag: 'div',
style: 'position: absolute; width: 16px; height: 16px; top: 5px; cursor: pointer; left: ' + parseInt((column.el.getWidth() - 16) / 2) + 'px',
cls: me.clearAllButtonIconCls,
'data-qtip': me.clearAllButtonTooltip
}));

me.clearAllEl.hide();
me.clearAllEl.on('click', function() {

me.showHideEl.show(); /* dsm 29 apr 14 : see also applyFilters */

me.clearFilters();
});
}
},





// private
applyFilters: function(field) {
if (!field.isValid()) return;
var me = this,
grid = me.grid,
column = me.columns.get(field.dataIndex),
newVal = (grid.store.remoteFilter ? field.getSubmitValue() : field.getValue());

/* dsm 29 apr 14 : probably in the wrong place... we have the red X not appearing on the filter row,
instead it is on the header row where the magnifying glass icon is to show/hide the filter row.
We'd like it on the filter row, but try this...
*/
if (me.showShowHideButton){ // dsm 23 may 14
me.showHideEl.hide(); // Hides the glass? Yes. See dsm tag same date above to show it again
}




I dunno if that if that is kosher, but it seems okay for now.

I see this in the comments...

* Applied a fix to rendering the column headers using the code from:
* http://www.sencha.com/forum/showthread.php?152923-Ext.ux.grid.FilterBar-plugin&p=1002888&viewfull=1#post1002888

... but the link does not lead to the post?

ognibendi2
15 Jul 2014, 1:08 AM
Hi, anybody got it working on ExtJS5?
I'm experiencing a problem with the grid.store.clearFilter() method not working
in the applyFilters function but i havent found a fix yet.
Thx

wki01
22 Jul 2014, 10:51 PM
Any plans to upgrade for 5 ExtJS ?

thank you very much

olecom
14 Aug 2014, 3:37 AM
How to make initial filtering ? For example, i want one of my columns to be filtered on grid load.

https://github.com/loiane/Ext.ux.grid.FilterBar/commit/6eefbeada2e9e63191734a808d644eef8360eff4

G1yyK
19 Aug 2014, 11:19 PM
Hello.

Why this plugin dont work with the TreeGrid, TreeGrid is grid same?
FilterBar shows search fields, but not sends request to server.

loiane
20 Aug 2014, 2:38 PM
Hello.

Why this plugin dont work with the TreeGrid, TreeGrid is grid same?
FilterBar shows search fields, but not sends request to server.

The plugin is only a helper. All the filter work is done by the store and your queries on the server.
Try adding remoteFilter: true in your store to see what is going to be sent to the server so you can handle it accordingly.

balaganesh.m
16 Oct 2014, 9:33 PM
Hi,

If anyone has FilterBar plugin for extjs version 5 please upload. this will be very much useful.

Thanks,
Bala

mcouillard
17 Oct 2014, 7:50 AM
I'm hopeful that 5.0's improved built-in column filter system is now good enough to avoid using a plugin. I haven't dove deep enough into though to tell.

wki01
19 Oct 2014, 4:20 AM
http://extjs.eu/announcement-grid-multisearch-plugin-compatible-with-extjs-5/

gtjw
3 Nov 2014, 3:49 AM
Hi, first of all great plugin!

I have one big problem, where I can't seem to find a way to fix it.
I have a grouped header and when I add the filters they don't get rendered properly.
They should be added ad the bottom of the header what works, but you don't see them, because thay are hidden under the first gridrow.
It looks like the headercontainer doesn’t resize when the filters are added.
Anybody a idea how to fix it?

gtjw
5 Nov 2014, 6:57 AM
I am working with Extjs plugin V 4.2.2 and version2013-11-15 by Loiane Groner.
I have the following questions:
1 - The header columns are not filtering completely:

49084


2 - At the scroll bar when there are many columns creates a strange and misaligned causing confusion:
49085

3 - The button to clean the filters does not look:

49086

Is there any solution?.

2 - At the scroll bar when there are many columns creates a strange and misaligned causing confusion.
Did you find a solution for this? I'm having the same issue with a lot (55) columns.