在组合框选择上过滤存储

时间:2012-11-14 15:36:58

标签: extjs combobox grid extjs4 extjs4.1

我尝试过这种方式,但仍无法使过滤器正常工作。我的ext应用程序允许用户从组合框中选择单个状态,下面的网格显示有关所选“值”=状态的更多数据。在选择时,组合框会触发一个过滤网格存储并更新存储的功能... 这是我的网格商店...

var store = Ext.create('Ext.data.Store', {
        autoLoad: true,
        id: 'OurData',
        pageSize: 20,
        pageNumber: 1,
        remoteSort: true,
        fields: [
    { name: 'States' },
    { name: 'FullName' },
    { name: 'Capital' },
    { name: 'Population' }
    ],
        proxy: {
            type: 'ajax',
            url: 'GetState/getS',
            reader: {
                type: 'json',
                root: 'myTable',
               idProperty: 'States',
                totalProperty: '@count'
            }
        }
    });
    store.loadPage(1);

这是我的组合框

xtype: 'combo',
                    id: 'iccombo',
                    scope: this,
                    store: this.Combostore,
                    fieldLabel: 'Short State',
                    displayField: 'States',
                    valueField: 'States',
                    typeAhead: true,
                    triggerAction: 'all',
                    queryMode: 'remote',
                    name: 'State',
                    labelWidth: 125,
                    anchor: '95%',
                    listeners: {
                        scope: this,
                        select: this.fireFilter
                    }

这就是过滤器应该发生的地方......

fireFilter: function (value) {

    // Get passed value
    this.selectedC = value.getValue();
    console.log('selectedValue: ' + this.selectedC);

    // Clear existing filters
    this.store.clearFilter(false);

    // Build filter

    var myfilter = Ext.create('Ext.util.Filter', {
        scope: this,
        filterFn: function (item) {
            var fieldNames = item.fields.keys;

            for (var j = 0; j < fieldNames.length; j++) {
                var fieldName = fieldNames[j];
                if (item.data[fieldName] != null) {
                    var stringVal = item.data[fieldName].toString();
                    if (stringVal != null && stringVal.toLowerCase().indexOf(value.toLowerCase()) != -1) {
                        return true;
                    }
                }
            }
            return false;
        }

    });
    // Apply filter to store
    this.store.filter(myfilter);
}

当我运行代码时,它显示网格中的所有数据,并且在选择组合框时,它仍显示相同的数据。 由于某种原因,代码永远不会通过filterFn ...因为我的console.log没有显示 这就是我在firebug的回应中得到的结果

_dc     1352902173425
filter  [{"property":null,"value":null}]
limit   20
page    1
start   0

你可以清楚地看到,所选的'value'是null,但是我的'console.log'打印了所选的值...我认为我得到传递值并应用过滤器的方式不正确...有人可以看看......谢谢

UPDATE ...我能够进入函数,我的console.log显示所有字段......但是一旦我到达最后一个if语句......我收到此错误

  

TypeError:value.toLowerCase不是函数

我在这里做错了什么?感谢

2 个答案:

答案 0 :(得分:4)

除了dbrin的anwser,我也无法理解你使用remoteSort而不是remoteFilter的原因?使用this时,您可能还会遇到范围问题。

无论如何,我建议你扩展一个新的组合类型,这样你也可以在需要的时候清除你的过滤器。这是我为自己编写的扩展。请注意,过滤本身需要在onSearch方法中实现,该方法可以是远程或本地排序。

Ext.define('Ext.ux.form.field.FilterCombo', {
    extend: 'Ext.form.field.ComboBox',
    alias: 'widget.filtercombo',
    /**
    * @cfg {string} recordField
    * @required
    * The fieldname of the record that contains the filtervalue
    */

    /**
    * @cfg {string} searchField
    * @required
    * The fieldname on which the filter should be applied
    */

    /**
    * @cfg {boolean} clearable
    * Indicates if the clear trigger should be hidden. Defaults to <tt>true</tt>.
    */
    clearable: true,

    initComponent: function () {
        var me = this;

        if (me.clearable)
            me.trigger2Cls = 'x-form-clear-trigger';
        else
            delete me.onTrigger2Click;

        me.addEvents(

            /**
            * @event clear
            *
            * @param {Ext.ux.form.field.FilterCombo} FilterCombo The filtercombo that triggered the event
            */
            'clear',
            /**
            * @event beforefilter
            *
            * @param {Ext.ux.form.field.FilterCombo} FilterCombo The filtercombo that triggered the event
            * @param {String/Number/Boolean/Float/Date} value The value to filter by
            * @param {string} field The field to filter on
            */
            'beforefilter'
        );

        me.callParent(arguments);
        // fetch the id the save way
        var ident = me.getId();

        me.on('select', function (me, rec) {
            var value = rec[0].data[me.recordField],
                field = me.searchField;
            me.fireEvent('beforefilter', me, value, field)
            me.onShowClearTrigger(true); 
            me.onSearch(value, field);
        }, me);
        me.on('afterrender', function () { me.onShowClearTrigger(); }, me);
    },

    /**
    * @abstract onSearch
    * running a search on the store that may be removed separately
    * @param {String/Number/Boolean/Float/Date} val The value to search for
    * @param {String} field The name of the Field to search on
    */
    onSearch: Ext.emptyFn,

    /**
    * @abstract onFilterRemove
    * removing filters from the the
    * @param {Boolean} silent Identifies if the filter should be removed without reloading the store
    */
    onClear: Ext.emptyFn,

    onShowClearTrigger: function (show) {
        var me = this;
        if (!me.clearable)
            return;
        show = (Ext.isBoolean(show)) ? show : false;
        if (show) {
            me.triggerEl.each(function (el, c, i) {
                if (i === 1) {
                    el.setWidth(el.originWidth, false);
                    el.setVisible(true);
                    me.active = true;
                }
            });
        } else {
            me.triggerEl.each(function (el, c, i) {
                if (i === 1) {
                    el.originWidth = el.getWidth();
                    el.setWidth(0, false);
                    el.setVisible(false);
                    me.active = false;
                }
            });
        }
        // Version specific methods
        if (Ext.lastRegisteredVersion.shortVersion > 407) {
            me.updateLayout();
        } else {
            me.updateEditState();
        }
    },

    /**
    * @override onTrigger2Click
    * eventhandler
    */
    onTrigger2Click: function (args) {
        this.clear();
    },

    /**
    * @private clear
    * clears the current search
    */
    clear: function () {
        var me = this;
        if (!me.clearable)
            return;
        me.onClear(false);
        me.clearValue();
        me.onShowClearTrigger(false);
        me.fireEvent('clear', me);
    }
});

这是您未经测试的组合实现。请注意,我清理了您的filterFn,但我没有进一步检查。

{
    xtype: 'filtercombo',
    id: 'iccombo',
    scope: this,
    store: this.Combostore,
    fieldLabel: 'Short State',
    displayField: 'States',
    valueField: 'States',   
    typeAhead: true,
    triggerAction: 'all',
    queryMode: 'remote',
    name: 'State',
    labelWidth: 125,
    anchor: '95%',
    // begin new parts
    recordField: 'States',
    searchField: '',
    clearable: false,
    onSearch: function (me, value, field) {

        // New part!
        var store = Ext.StoreMgr.lookup('YourStoreIdName');

        // Clear existing filters
        store.clearFilter(false);

        // Build filter
        var myfilter = Ext.create('Ext.util.Filter', {
        scope: this,
        filterFn: function (item) {
            var fieldNames = item.fields.keys,
                fieldName, stringVal,
                len = fieldNames.length,
                j = 0;

            for (; j < len; j++) {
                fieldName = fieldNames[j];
                if (item.data[fieldName] != null) {
                    stringVal = item.data[fieldName].toString();
                    if (stringVal != null && stringVal.toLowerCase().indexOf(value.toLowerCase()) != -1) {
                        return true;
                    }
                }
            }
            return false;
        }
    });
        // Apply filter to store
        store.filter(myfilter);
    }
}

我想这也应该有用

var myfilter = Ext.create('Ext.util.Filter', {
            scope: this,
            filterFn: function (rec) {
                var fieldValue = rec[this.fieldName];
                if (fieldValue && fieldValue === this.value)
                      return true;
            return false;
            }
        });

我在两个vars之前设置this以将它们标记为来自外部范围。

答案 1 :(得分:1)

我看到2个问题

  1. 商店应该设置remoteFilter: true

  2. 在JavaScript中
  3. 选取所有变量声明并将其提升到函数的开头。所以在循环中声明的任何变量都应该被取出并在函数的顶部声明。 JS没有块范围(如Java)。