View Full Version : [OPEN-1252] getFilterClass not fully working when filters defined in columnModel

2 Sep 2010, 1:35 AM
Ext version tested:

Ext 3.2.1

Adapter used:


css used:

only default ext-all.css

Browser versions tested against:

Chromium 7
FF3 (firebug installed)

Operating System:

Ubuntu 10.04


When the filters to use are defined in the columnModel you are also forced to specify to type.
You have to specify the type when the filters are separated from the columnModel, but this is expected behavior.
GridFilters is designed to retrieve the type from the store if it's not defined in the filter. But it compares the field type with strings in the metod getFilterClass(type); and, as the 3.2.0 changelog (http://www.sencha.com/products/js/CHANGES_ext-3.2.0.html) states, this is wrong and has to be changed.
There will be a small breaking change, when interrogating the type of a field, it will now return a type object.

Test Case:

Tried to copy the filters example from the ExtJS demos, but couldn't make it work. But all you have to do is remove the filters definition and let the grid filters be built based on the column model, which as the source comments explicitly point out should be enough to make it work without even defining the field types.

cm: new Ext.grid.ColumnModel({
columns: [
{header: "WorkingColumn", dataIndex: "first", filter: {type: "int"}},
{header: "NotWorkingColumn", dataIndex: "second", filter: {}},
{header: "NotWorkingFilterableColumn", dataIndex: "third", filterable: true},
{header: "WorkingListFilter", dataIndex: "fourth", filter: {type: "list", options: ["small", "medium", "large", "extra large"]}}

Steps to reproduce the problem:

Modify the grid filters demo and remove the filters definition (and plugin) to use only the definition from the column model.

The result that was expected:

GridFilters retrieves the field types from the store definition and builds the filters properly.

The result that occurs instead:

Error in the last line of GridFilter.getFilterClass(type) since 'type' is not a string anymore when retrieved from the field definition in the store: type.substr is not a function

Debugging already done:

A lot

Possible fix: Tested and working.

* Adds filters to the collection.
* @param {Array/Ext.grid.ColumnModel} filters Either an Array of
* filter configuration objects or an Ext.grid.ColumnModel. The columns
* of a passed Ext.grid.ColumnModel will be examined for a <code>filter</code>
* property and, if present, will be used as the filter configuration object.
addFilters : function (filters) {
if (filters) {
var i, len, filter, cm = false, dI;
if (filters instanceof Ext.grid.ColumnModel) {
filters = filters.config;
cm = true;
for (i = 0, len = filters.length; i < len; i++) {
filter = false;
if (cm) {
dI = filters[i].dataIndex;
filter = filters[i].filter || filters[i].filterable;
if (filter){
filter = (filter === true) ? {} : filter;
Ext.apply(filter, {dataIndex:dI});
// filter type is specified in order of preference:
// filter type specified in config
// type specified in store's field's type config
filter.type = filter.type || this.store.fields.get(dI).type.type;
} else {
filter = filters[i];
// if filter config found add filter for the column
if (filter) {

2 Sep 2010, 6:41 AM
While you are at it, it would also be a nice feature to add something like the following code to the StringFilter. It will make things easier in many cases.
* The code follows the filtering process found in Store.filter() -> createFilterFn() -> Ext.util.MixedCollection.createValueMatcher().
* I don't know if StringFilter should use a different filtering.

Ext.ux.grid.filter.CustomStringFilter = Ext.extend(Ext.ux.grid.filter.StringFilter, {
* @cfg {Boolean} anyMatch <tt>true</tt> to match any part not just the beginning (defaults to <tt>false</tt>).
anyMatch : true,
* @cfg {Boolean} caseSensitive <tt>true</tt> for case sensitive comparison (defaults to <tt>false</tt>).
caseSensitive : false,
* @cfg {Boolean} exactMatch <tt>true</tt> to force exact match (^ and $ characters added to the regex) (defaults to <tt>false</tt>).
* <p><b>Note</b>: Ignored if anyMatch is <tt>true</tt>.
exactMatch : false,
* Template method that is to validate the provided Ext.data.Record
* against the filters configuration.
* @param {Ext.data.Record} record The record to validate
* @return {Boolean} true if the record is valid within the bounds
* of the filter, false otherwise.
validateRecord : function (record) {
var value = record.get(this.dataIndex);
var matcherValue = this.getValue();

if (typeof value != 'string') {
return (matcherValue.length === 0);

var matcher = record.store.data.createValueMatcher(matcherValue, this.anyMatch, this.caseSensitive, this.exactMatch);
return matcher.test(value);