user3524762
user3524762

Reputation: 642

ComboBox typeAhead works but valueField is null under certain behavioral conditions

Requesting a sanity check here please...

ExtJS 4.2 comboBox Typeahead works but having issues retrieving the valueField under the following conditions:-

1) If a user types a value and then instead of hitting enter or clicking on the select combo list, they click elsewhere then the valueField is empty but the selected value is present.

2) Assuming that the combobox item was selected correctly, If I enter an additional character and then backspace that character, the combo box can no longer find the valueField..its almost like it has reset itself.

Fiddle example

https://fiddle.sencha.com/#fiddle/je1

How to reproduce

If you enter Maggie in the combo box, you will see the valueField ID in the console window, if you append a character and then backspace the character, the ID in the console window is null

(You will need to open the console window to see the output)

forceSelection does not resolve this issue as I have a template and it will not accept an entry in the combobox that is not part of the store, and I need to use sumID for my valueField as I need to retrieve and pass that value to the server.

Upvotes: 1

Views: 904

Answers (2)

user3524762
user3524762

Reputation: 642

Thank you everyone, awesome to have such a great community!!

I was able to get around this by using forceSelection and overriding the setValue thus allowing template items not in the store but in the combo to be selected via forceSelection. From playing around with the combobox, IMO, for a good look and feel, forceSelection is the way to go.

Here is my override, refer to statement //start of override

This was a quick fix, I will refine statement when I am back in the office, below I am pasting the solution from memory, you get the idea.

setValue: function(value, doSelect) {
        var me = this,
            valueNotFoundText = me.valueNotFoundText,
            inputEl = me.inputEl,
            i, len, record,
            dataObj,
            matchedRecords = [],
            displayTplData = [],
            processedValue = [];

        if (me.store.loading) {
            // Called while the Store is loading. Ensure it is processed by the onLoad method.
            me.value = value;
            me.setHiddenValue(me.value);
            return me;
        }

        // This method processes multi-values, so ensure value is an array.
        value = Ext.Array.from(value);

        // Loop through values, matching each from the Store, and collecting matched records
        for (i = 0, len = value.length; i < len; i++) {
            record = value[i];
            if (!record || !record.isModel) {
                record = me.findRecordByValue(record);
            }
            // record found, select it.
            if (record) {
                matchedRecords.push(record);
                displayTplData.push(record.data);
                processedValue.push(record.get(me.valueField));
            }
            // record was not found, this could happen because
            // store is not loaded or they set a value not in the store
            else {
            //start of override

            // 'Select All Names' is the template item that was added                                     // to the combo box,  it looks like an entry from the store         
            // but it is not in the store
            if (me.forceSelection && me.getDisplayValue() === 'Select All Names'){
                    processedValue.push(value[i]);
                    dataObj = {};
                    dataObj[me.displayField] = value[i];
                    displayTplData.push(dataObj);
                }
                //end of override

                if (!me.forceSelection) {
                    processedValue.push(value[i]);
                    dataObj = {};
                    dataObj[me.displayField] = value[i];
                    displayTplData.push(dataObj);
                    // TODO: Add config to create new records on selection of a value that has no match in the Store
                }
                // Else, if valueNotFoundText is defined, display it, otherwise display nothing for this value
                else if (Ext.isDefined(valueNotFoundText)) {
                    displayTplData.push(valueNotFoundText);
                }
            }
        }

    // Set the value of this field. If we are multiselecting, then that is an array.
    me.setHiddenValue(processedValue);
    me.value = me.multiSelect ? processedValue : processedValue[0];
    if (!Ext.isDefined(me.value)) {
        me.value = null;
    }
    me.displayTplData = displayTplData; //store for getDisplayValue method
    me.lastSelection = me.valueModels = matchedRecords;

    if (inputEl && me.emptyText && !Ext.isEmpty(value)) {
        inputEl.removeCls(me.emptyCls);
    }

    // Calculate raw value from the collection of Model data
    me.setRawValue(me.getDisplayValue());
    me.checkChange();

    if (doSelect !== false) {
        me.syncSelection();
    }
    me.applyEmptyText();

    return me;
},

Upvotes: 1

Abylay Sabirgaliyev
Abylay Sabirgaliyev

Reputation: 726

Look at the sources of Combobox and try override this method as follows

doLocalQuery: function(queryPlan) {
    var me = this,
        queryString = queryPlan.query;


    if (!me.queryFilter) {

        me.queryFilter = new Ext.util.Filter({
            id: me.id + '-query-filter',
            anyMatch: me.anyMatch,
            caseSensitive: me.caseSensitive,
            root: 'data',
            property: me.displayField
        });
        me.store.addFilter(me.queryFilter, false);
    }


    if (queryString || !queryPlan.forceAll) {
        me.queryFilter.disabled = false;
        me.queryFilter.setValue(me.enableRegEx ? new RegExp(queryString) : queryString);
    }


    else {
        me.queryFilter.disabled = true;
    }


    me.store.filter();


    if (me.store.getCount()) {
        if (me.rawValue === me.lastSelection[0].get(me.displayField)){
            me.setValue(me.lastSelection);
        } else {
            if(me.store.getCount() === 1){
                me.setValue(me.store.first());
            }
            me.expand();
        }
    } else {
        me.collapse();
    }

    me.afterQuery(queryPlan);
},

Upvotes: 0

Related Questions