1

The combobox in modern fires the "select" event every time the input changes. This is very different from classic. With it doing this there is no way to differentiate between a user making a selection and pragmatically setting the value of the field.

This was reported as a bug in the Sencha forums:

https://www.sencha.com/forum/showthread.php?468730-Modern-6-5-2-ComboBox-fires-select-event-on-every-value-change

The link above also contains a fiddler to demonstrate the issue.

Has anyone run into this as an issue, and how did you overcome it?

nathan
  • 13
  • 2

1 Answers1

1

forceSelection: true will help to solve this problem but will not cancel the bug in cases when forced selection is not needed

Edit:

This behavior is due to method syncValue (search in this source - method is private and hasn't documentation)

I don’t understand why the component developer chose to create a record even if it isn’t exist.

Comment from source file:

Either user has typed something (isInput), or we've had a setValue to a value which has no match in the store, and we are not forceSelection: true. We create a new record.

I propose to fix this behavior using the following override:

fiddle

Ext.define('Ext.field.SelectOverride', {
    override: 'Ext.field.Select',
    autoCreateRecord: false,
    syncValue: function() {
        var me = this,
            store = me.getStore(),
            forceSelection = me.getForceSelection(),
            valueNotFoundText = me.getValueNotFoundText(),
            is, isCleared, isInput, value, matchedRecord;


        if (me.reconcilingValue || !store || !store.isLoaded() || store.hasPendingLoad()) {
            return;
        }

        me.reconcilingValue = true;

        me.getSelection(); // make sure selection config is flushed

        is = {};
        is[me.syncMode] = true;
        value = ((isInput = is.input || is.filter)) ? me.getInputValue() : me.getValue();
        isCleared = value == null || value === '';


        if (!isCleared) {
            if (me.getMultiSelect()) {
                return me.syncMultiValues(Ext.Array.from(value));
            }

            matchedRecord = (isInput ? store.byText : store.byValue).get(value);

            if (matchedRecord) {
                if (!matchedRecord.isEntity) {

                    matchedRecord = matchedRecord[0];
                }
            }
            else if (!forceSelection) {
                matchedRecord = me.findRecordByValue(value);
            }
        }

        // Either user has typed something (isInput), or we've had a setValue
        // to a value which has no match in the store, and we are not forceSelection: true.
        // We create a new record.
        if (!isCleared && !matchedRecord && !forceSelection && me.autoCreateRecord) {
            matchedRecord = me.createEnteredRecord(value);
        }
        else {
            if (isInput || is.store) {
                if (!matchedRecord && forceSelection) {
                    me.setValue(null);
                    me.setSelection(null);

                    if (!is.filter) {
                        me.setFieldDisplay();
                    }
                }
            }            else {
                if (isCleared) {
                    if (me.mustAutoSelect()) {
                        matchedRecord = store.first();

                        if (me.getAutoSelect() === 'initial') {
                            me.setAutoSelect(false);
                        }
                    }
                    else {
                        me.setSelection(null);
                    }
                }
                else if (!matchedRecord && valueNotFoundText) {
                    me.setError(valueNotFoundText);
                }
            }
        }

        if (matchedRecord) {
            me.setSelection(matchedRecord);
        }

        me.reconcilingValue = false;
    }
});
pvlt
  • 1,843
  • 1
  • 10
  • 19
  • Thank you for the response, Yes, that does seem to stop the "select" being fired for every input change. In my specific scenario I need forceSelection: true. When I load the record into the form, I set the initial value of the combobox with a mock record. That initial value set fires "select", but it doesn't do that in classic. And I have controller code that works with both classic and modern, so the modern combobox is breaking my shared logic. – nathan Feb 27 '20 at 20:38
  • In my opinion most often in combo is useful `forceSelection: true`. That strange it doesn’t default value. Happy to help and welcome to StackOverflow. If this answer or any other one solved your issue, please mark it as accepted – pvlt Feb 27 '20 at 21:13
  • There are so many issue with the combobox component, its hard to pinpoint them all. Combobox is by far the component I have to override and change behavior the most. – nathan Feb 27 '20 at 22:36