简体   繁体   English

在组合框选择上过滤存储

[英]Filter store on combobox selection

I have tried this different ways, but still can't get the filter to work. 我尝试过这种不同的方法,但仍无法使过滤器工作。 My ext app lets user to choose a single state from a combobox, and the grid below displays more data on that selected "value"=state.. On select, the combobox fires a function that filters the store of the grid and updates the store... this is my store for the grid... 我的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);

this is my combobox 这是我的组合框

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
                    }

and this is where the filter should take place... 这是过滤器应该发生的地方......

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);
}

when I run the code, it display all data in the grid, and on selection of combobox, it still shows the same data.. For some reason, the code never runs through the filterFn... because my console.log doesn't show up this is what I got in firebug's response 当我运行代码时,它显示网格中的所有数据,并且在选择组合框时,它仍然显示相同的数据..由于某种原因,代码永远不会通过filterFn ...因为我的console.log没有出现这是我在firebug的回应中得到的

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

as you can clearly see, the selected 'value' is null, but my 'console.log' prints the value selected... I think the way I am getting the passed value and applying the filter is incorrect... can someone please take a look... thanks 你可以清楚地看到,所选的“值”为空,但我的'console.log'打印选定的值...我认为我获得传递值并应用过滤器的方式不正确...有人可以请看看......谢谢

UPDATE... I am able to get inside the function and my console.log shows all the fields... but once I get to the last if statement... I get this error 更新...我能够进入函数,我的console.log显示所有字段...但是一旦我到达最后一个if语句...我得到这个错误

TypeError: value.toLowerCase is not a function TypeError:value.toLowerCase不是函数

What am I doing wrong here? 我在这做错了什么? Thanks 谢谢

In addition to dbrin's anwser I also can't understand why you are using remoteSort but not remoteFilter ? 除了dbrin的anwser,我也无法理解你为什么使用remoteSort而不是remoteFilter You may also have a scope issue by using this . 使用this也可能会导致范围问题。

Anyway I would recommend you to extend a new combo type so that you are also be able to clear your filter if you have the need to. 无论如何,我建议你扩展一个新的组合类型,这样你也可以在需要的时候清除你的过滤器。 Here is an extension I have written for my own use. 这是我为自己编写的扩展。 Note that the filtering itself needs to be implemented in the onSearch method, which can be either a remote or a local sort. 请注意,过滤本身需要在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);
    }
});

Here is an untested implementation of your combo. 这是一个未经测试的组合实现。 Please note that I cleaned up your filterFn but I didn't make any further check. 请注意,我清理了你的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);
    }
}

I guess this should work too 我想这也应该有效

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;
            }
        });

I set this before two vars to mark them as from a external scope. 我在两个vars之前设置this以将它们标记为来自外部范围。

i see 2 issues 我看到2个问题

  1. store should have remoteFilter: true set store应该有remoteFilter: true set

  2. in JavaScript all variables declarations are picked out and hoisted to the beginning of the function. 在JavaScript中,所有变量声明都被挑选出来并提升到函数的开头。 so any variables declared inside a loop should be taken out and declared at the top of the function. 所以在循环中声明的任何变量都应该被取出并在函数的顶部声明。 JS has no block scope (like Java). JS没有块范围(如Java)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM