Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/379.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/extjs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript ExtJS:重新选择相同的值不会触发select事件_Javascript_Extjs - Fatal编程技术网

Javascript ExtJS:重新选择相同的值不会触发select事件

Javascript ExtJS:重新选择相同的值不会触发select事件,javascript,extjs,Javascript,Extjs,通常,当您在组合框中选择一个项目时,您希望它触发select事件。但是,如果尝试选择已选择的项目,则不会触发select事件。这是ExtJs组合框的“正常”行为 我特别需要一个ExtJS组合框:我需要它来触发select事件,即使我重新选择了相同的值。但是我不能让它工作。任何帮助都将不胜感激 示例如下: 打开开发工具以查看何时触发select事件 我使用的是ExtJS Classic 6.6.0 编辑:我回答了自己的问题,并更新了Fiddle with working解决方案。试着看看这个:

通常,当您在组合框中选择一个项目时,您希望它触发select事件。但是,如果尝试选择已选择的项目,则不会触发select事件。这是ExtJs组合框的“正常”行为

我特别需要一个ExtJS组合框:我需要它来触发select事件,即使我重新选择了相同的值。但是我不能让它工作。任何帮助都将不胜感激

示例如下: 打开开发工具以查看何时触发select事件

我使用的是ExtJS Classic 6.6.0

编辑:我回答了自己的问题,并更新了Fiddle with working解决方案。

试着看看这个:

它适用于早期的ExtJS版本,但捕获itemlist的单击事件也可能会帮助您解决此问题。

请尝试查看以下内容:


它适用于早期的ExtJS版本,但捕获itemlist的单击事件也可能会帮助您解决问题。

我找到了罪魁祸首:这一切都发生在组合框边界列表的SelectionModel中,即Selection方法中

因此,如果我们扩展Ext.Selection.DataViewModel和Ext.form.field.ComboBox,我们可以强制每次触发select事件

Ext.define( "MyApp.selection.DataViewModelExt", {
    "extend": "Ext.selection.DataViewModel",
    "alias": "selection.dataviewmodelext",

    "doSingleSelect": function(record, suppressEvent) {
        var me = this,
            changed = false,
            selected = me.selected,
            commit;

        if (me.locked) {
            return;
        }
        // already selected. 
        // should we also check beforeselect? 
        /*
        if (me.isSelected(record)) {
            return;
        }
        */

        commit = function() {
            // Deselect previous selection. 
            if (selected.getCount()) {
                me.suspendChanges();
                var result = me.deselectDuringSelect([record], suppressEvent);
                if (me.destroyed) {
                    return;
                }
                me.resumeChanges();
                if (result[0]) {
                    // Means deselection failed, so abort 
                    return false;
                }
            }

            me.lastSelected = record;
            if (!selected.getCount()) {
                me.selectionStart = record;
            }
            selected.add(record);
            changed = true;
        };

        me.onSelectChange(record, true, suppressEvent, commit);

        if (changed && !me.destroyed) {
            me.maybeFireSelectionChange(!suppressEvent);
        }
    }
});
我们还必须扩展combobox以强制使用扩展的DataViewModel。唯一需要更改的是onBindStore方法,它在其中实例化DataViewModel:

Ext.define( "MyApp.form.field.ComboBoxEx", {
    "extend": "Ext.form.field.ComboBox",
    "alias": "widget.comboboxex",

    "onBindStore": function(store, initial) {
        var me = this,
            picker = me.picker,
            extraKeySpec,
            valueCollectionConfig;

        // We're being bound, not unbound... 
        if (store) {
            // If store was created from a 2 dimensional array with generated field names 'field1' and 'field2' 
            if (store.autoCreated) {
                me.queryMode = 'local';
                me.valueField = me.displayField = 'field1';
                if (!store.expanded) {
                    me.displayField = 'field2';
                }

                // displayTpl config will need regenerating with the autogenerated displayField name 'field1' 
                if (me.getDisplayTpl().auto) {
                    me.setDisplayTpl(null);
                }
            }
            if (!Ext.isDefined(me.valueField)) {
                me.valueField = me.displayField;
            }

            // Add a byValue index to the store so that we can efficiently look up records by the value field 
            // when setValue passes string value(s). 
            // The two indices (Ext.util.CollectionKeys) are configured unique: false, so that if duplicate keys 
            // are found, they are all returned by the get call. 
            // This is so that findByText and findByValue are able to return the *FIRST* matching value. By default, 
            // if unique is true, CollectionKey keeps the *last* matching value. 
            extraKeySpec = {
                byValue: {
                    rootProperty: 'data',
                    unique: false
                }
            };
            extraKeySpec.byValue.property = me.valueField;
            store.setExtraKeys(extraKeySpec);

            if (me.displayField === me.valueField) {
                store.byText = store.byValue;
            } else {
                extraKeySpec.byText = {
                    rootProperty: 'data',
                    unique: false
                };
                extraKeySpec.byText.property = me.displayField;
                store.setExtraKeys(extraKeySpec);
            }

            // We hold a collection of the values which have been selected, keyed by this field's valueField. 
            // This collection also functions as the selected items collection for the BoundList's selection model 
            valueCollectionConfig = {
                rootProperty: 'data',
                extraKeys: {
                    byInternalId: {
                        property: 'internalId'
                    },
                    byValue: {
                        property: me.valueField,
                        rootProperty: 'data'
                    }
                },
                // Whenever this collection is changed by anyone, whether by this field adding to it, 
                // or the BoundList operating, we must refresh our value. 
                listeners: {
                    beginupdate: me.onValueCollectionBeginUpdate,
                    endupdate: me.onValueCollectionEndUpdate,
                    scope: me
                }
            };

            // This becomes our collection of selected records for the Field. 
            me.valueCollection = new Ext.util.Collection(valueCollectionConfig);

            // This is the selection model we configure into the dropdown BoundList. 
            // We use the selected Collection as our value collection and the basis 
            // for rendering the tag list.
            //me.pickerSelectionModel = new Ext.selection.DataViewModel({
            me.pickerSelectionModel = new MyApp.selection.DataViewModelExt({
                mode: me.multiSelect ? 'SIMPLE' : 'SINGLE',
                // There are situations when a row is selected on mousedown but then the mouse is dragged to another row 
                // and released.  In these situations, the event target for the click event won't be the row where the mouse 
                // was released but the boundview.  The view will then determine that it should fire a container click, and 
                // the DataViewModel will then deselect all prior selections. Setting `deselectOnContainerClick` here will 
                // prevent the model from deselecting. 
                ordered: true,
                deselectOnContainerClick: false,
                enableInitialSelection: false,
                pruneRemoved: false,
                selected: me.valueCollection,
                store: store,
                listeners: {
                    scope: me,
                    lastselectedchanged: me.updateBindSelection
                }
            });

            if (!initial) {
                me.resetToDefault();
            }

            if (picker) {
                me.pickerSelectionModel.on({
                    scope: me,
                    beforeselect: me.onBeforeSelect,
                    beforedeselect: me.onBeforeDeselect
                });

                picker.setSelectionModel(me.pickerSelectionModel);

                if (picker.getStore() !== store) {
                    picker.bindStore(store);
                }
            }
        }
    }
});

然后只需在应用程序中使用扩展组合框。通过这样做,每次都会触发select事件。

我找到了罪魁祸首:这一切都发生在组合框边界列表的SelectionModel中的select方法中

Ext.define( "MyApp.selection.DataViewModelExt", {
    "extend": "Ext.selection.DataViewModel",
    "alias": "selection.dataviewmodelext",

    "doSingleSelect": function(record, suppressEvent) {
        var me = this,
            changed = false,
            selected = me.selected,
            commit;

        if (me.locked) {
            return;
        }
        // already selected. 
        // should we also check beforeselect? 
        /*
        if (me.isSelected(record)) {
            return;
        }
        */

        commit = function() {
            // Deselect previous selection. 
            if (selected.getCount()) {
                me.suspendChanges();
                var result = me.deselectDuringSelect([record], suppressEvent);
                if (me.destroyed) {
                    return;
                }
                me.resumeChanges();
                if (result[0]) {
                    // Means deselection failed, so abort 
                    return false;
                }
            }

            me.lastSelected = record;
            if (!selected.getCount()) {
                me.selectionStart = record;
            }
            selected.add(record);
            changed = true;
        };

        me.onSelectChange(record, true, suppressEvent, commit);

        if (changed && !me.destroyed) {
            me.maybeFireSelectionChange(!suppressEvent);
        }
    }
});
因此,如果我们扩展Ext.Selection.DataViewModel和Ext.form.field.ComboBox,我们可以强制每次触发select事件

Ext.define( "MyApp.selection.DataViewModelExt", {
    "extend": "Ext.selection.DataViewModel",
    "alias": "selection.dataviewmodelext",

    "doSingleSelect": function(record, suppressEvent) {
        var me = this,
            changed = false,
            selected = me.selected,
            commit;

        if (me.locked) {
            return;
        }
        // already selected. 
        // should we also check beforeselect? 
        /*
        if (me.isSelected(record)) {
            return;
        }
        */

        commit = function() {
            // Deselect previous selection. 
            if (selected.getCount()) {
                me.suspendChanges();
                var result = me.deselectDuringSelect([record], suppressEvent);
                if (me.destroyed) {
                    return;
                }
                me.resumeChanges();
                if (result[0]) {
                    // Means deselection failed, so abort 
                    return false;
                }
            }

            me.lastSelected = record;
            if (!selected.getCount()) {
                me.selectionStart = record;
            }
            selected.add(record);
            changed = true;
        };

        me.onSelectChange(record, true, suppressEvent, commit);

        if (changed && !me.destroyed) {
            me.maybeFireSelectionChange(!suppressEvent);
        }
    }
});
我们还必须扩展combobox以强制使用扩展的DataViewModel。唯一需要更改的是onBindStore方法,它在其中实例化DataViewModel:

Ext.define( "MyApp.form.field.ComboBoxEx", {
    "extend": "Ext.form.field.ComboBox",
    "alias": "widget.comboboxex",

    "onBindStore": function(store, initial) {
        var me = this,
            picker = me.picker,
            extraKeySpec,
            valueCollectionConfig;

        // We're being bound, not unbound... 
        if (store) {
            // If store was created from a 2 dimensional array with generated field names 'field1' and 'field2' 
            if (store.autoCreated) {
                me.queryMode = 'local';
                me.valueField = me.displayField = 'field1';
                if (!store.expanded) {
                    me.displayField = 'field2';
                }

                // displayTpl config will need regenerating with the autogenerated displayField name 'field1' 
                if (me.getDisplayTpl().auto) {
                    me.setDisplayTpl(null);
                }
            }
            if (!Ext.isDefined(me.valueField)) {
                me.valueField = me.displayField;
            }

            // Add a byValue index to the store so that we can efficiently look up records by the value field 
            // when setValue passes string value(s). 
            // The two indices (Ext.util.CollectionKeys) are configured unique: false, so that if duplicate keys 
            // are found, they are all returned by the get call. 
            // This is so that findByText and findByValue are able to return the *FIRST* matching value. By default, 
            // if unique is true, CollectionKey keeps the *last* matching value. 
            extraKeySpec = {
                byValue: {
                    rootProperty: 'data',
                    unique: false
                }
            };
            extraKeySpec.byValue.property = me.valueField;
            store.setExtraKeys(extraKeySpec);

            if (me.displayField === me.valueField) {
                store.byText = store.byValue;
            } else {
                extraKeySpec.byText = {
                    rootProperty: 'data',
                    unique: false
                };
                extraKeySpec.byText.property = me.displayField;
                store.setExtraKeys(extraKeySpec);
            }

            // We hold a collection of the values which have been selected, keyed by this field's valueField. 
            // This collection also functions as the selected items collection for the BoundList's selection model 
            valueCollectionConfig = {
                rootProperty: 'data',
                extraKeys: {
                    byInternalId: {
                        property: 'internalId'
                    },
                    byValue: {
                        property: me.valueField,
                        rootProperty: 'data'
                    }
                },
                // Whenever this collection is changed by anyone, whether by this field adding to it, 
                // or the BoundList operating, we must refresh our value. 
                listeners: {
                    beginupdate: me.onValueCollectionBeginUpdate,
                    endupdate: me.onValueCollectionEndUpdate,
                    scope: me
                }
            };

            // This becomes our collection of selected records for the Field. 
            me.valueCollection = new Ext.util.Collection(valueCollectionConfig);

            // This is the selection model we configure into the dropdown BoundList. 
            // We use the selected Collection as our value collection and the basis 
            // for rendering the tag list.
            //me.pickerSelectionModel = new Ext.selection.DataViewModel({
            me.pickerSelectionModel = new MyApp.selection.DataViewModelExt({
                mode: me.multiSelect ? 'SIMPLE' : 'SINGLE',
                // There are situations when a row is selected on mousedown but then the mouse is dragged to another row 
                // and released.  In these situations, the event target for the click event won't be the row where the mouse 
                // was released but the boundview.  The view will then determine that it should fire a container click, and 
                // the DataViewModel will then deselect all prior selections. Setting `deselectOnContainerClick` here will 
                // prevent the model from deselecting. 
                ordered: true,
                deselectOnContainerClick: false,
                enableInitialSelection: false,
                pruneRemoved: false,
                selected: me.valueCollection,
                store: store,
                listeners: {
                    scope: me,
                    lastselectedchanged: me.updateBindSelection
                }
            });

            if (!initial) {
                me.resetToDefault();
            }

            if (picker) {
                me.pickerSelectionModel.on({
                    scope: me,
                    beforeselect: me.onBeforeSelect,
                    beforedeselect: me.onBeforeDeselect
                });

                picker.setSelectionModel(me.pickerSelectionModel);

                if (picker.getStore() !== store) {
                    picker.bindStore(store);
                }
            }
        }
    }
});

然后只需在应用程序中使用扩展组合框。通过这样做,每次都会触发select事件。

为什么-1没有任何解释?为什么-1没有任何解释?谢谢,它给了我应该做什么的提示。我将用解决方案回答我的问题,因为它与此答案有点不同(我想要的是选择事件,而不是单击事件)。谢谢,它给了我应该做什么的指针。我将用解决方案回答我的问题,因为它与此答案略有不同(我希望选择事件,而不是单击事件)。
Ext.define( "MyApp.selection.DataViewModelExt", {
    "extend": "Ext.selection.DataViewModel",
    "alias": "selection.dataviewmodelext",

    "doSingleSelect": function(record, suppressEvent) {
        var me = this,
            changed = false,
            selected = me.selected,
            commit;

        if (me.locked) {
            return;
        }
        // already selected. 
        // should we also check beforeselect? 
        /*
        if (me.isSelected(record)) {
            return;
        }
        */

        commit = function() {
            // Deselect previous selection. 
            if (selected.getCount()) {
                me.suspendChanges();
                var result = me.deselectDuringSelect([record], suppressEvent);
                if (me.destroyed) {
                    return;
                }
                me.resumeChanges();
                if (result[0]) {
                    // Means deselection failed, so abort 
                    return false;
                }
            }

            me.lastSelected = record;
            if (!selected.getCount()) {
                me.selectionStart = record;
            }
            selected.add(record);
            changed = true;
        };

        me.onSelectChange(record, true, suppressEvent, commit);

        if (changed && !me.destroyed) {
            me.maybeFireSelectionChange(!suppressEvent);
        }
    }
});