Page 1 of 2 12 LastLast
Results 1 to 10 of 13

Thread: How To Re-Empty ComboBox when forceSelection is Set To TRUE

  1. #1
    Sencha User
    Join Date
    Oct 2008
    Posts
    30
    Vote Rating
    0
      0  

    Default How To Re-Empty ComboBox when forceSelection is Set To TRUE

    I have a combo box with 'forceSelection' config is set to true.

    The combo box is optional. It can be empty.

    If user choose one of the options and then re-empty the combo box, it doesn't want to be empty.

    The combo box always restores the previously selected value.

    It's ridiculous. It should be empty when user delete the value.

    How to solve this problem? Is there a config that I missed?

    Thank you very much.

  2. #2
    Sencha User
    Join Date
    Jan 2012
    Posts
    1,376
    Vote Rating
    117
      2  

    Default

    I think this is the nature of Ext combo box with forceSelection set to true, especially when multiSelect set to false. You can check this by looking at its code:
    Code:
    assertValue: function() {
        var me = this,
            value = me.getRawValue(),
            rec;
    
    
        if (me.forceSelection) {
            if (me.multiSelect) {
                // For multiselect, check that the current displayed value matches the current
                // selection, if it does not then revert to the most recent selection.
                if (value !== me.getDisplayValue()) {
                    me.setValue(me.lastSelection);
                }
            } else {
                // For single-select, match the displayed value to a record and select it,
                // if it does not match a record then revert to the most recent selection.
                rec = me.findRecordByDisplay(value);
                if (rec) {
                    me.select(rec);
                } else {
                    me.setValue(me.lastSelection);
                }
            }
        }
        me.collapse();
    },
    However, if you still want to empty the combo box when user delete the value, you could do it as follow:
    Code:
    Ext.create('Ext.form.field.ComboBox', {
        ...
        allowBlank: true,
        forceSelection: true,
        beforeBlur: function(){
            var value = this.getRawValue();
            if(value == ''){
                this.lastSelection = [];
            }
            this.doQueryTask.cancel();
            this.assertValue();
        }
    });

  3. #3
    Sencha User
    Join Date
    Oct 2008
    Posts
    30
    Vote Rating
    0
      0  

    Default

    Quote Originally Posted by vietits View Post
    I think this is the nature of Ext combo box with forceSelection set to true, especially when multiSelect set to false. You can check this by looking at its code:<br>
    Thank you for the reply, @vietits.

    However, if that's the nature of combobox as you said, then why it's considered valid if empty?

    In my understanding, forceSelection means: "Choose one from the list. And if you don't want to choose, just leave it empty. You can't type arbitrary value."

  4. #4
    Sencha User
    Join Date
    Jan 2012
    Posts
    1,376
    Vote Rating
    117
      0  

    Default

    However, if that's the nature of combobox as you said, then why it's considered valid if empty?
    Do you mean the config of allowBlank: true? I think this config does not affect to the working of combo box but only used for validating form.


    In my understanding, forceSelection means: "Choose one from the list. And if you don't want to choose, just leave it empty. You can't type arbitrary value."
    Maybe you are right and you can send this as a request to the development team.

  5. #5
    Sencha User
    Join Date
    Oct 2008
    Posts
    30
    Vote Rating
    0
      0  

    Default

    Quote Originally Posted by vietits View Post
    Do you mean the config of allowBlank: true? I think this config does not affect to the working of combo box but only used for validating form.
    No. I mean forceSelection: true.

    Why is it considered to be valid if user doesn't touch it (leave it empty).

    But after the user touch it, it cannot be re-emptied. I think it's really ridiculous.

    Quote Originally Posted by vietits View Post
    Maybe you are right and you can send this as a request to the development team.
    The documentation already said that when forceSelection: true, user just cannot type arbitrary value.
    I think it is already the same as my understanding. It's just the implementation which doesn't behave like what it is supposed to be.

  6. #6
    Touch Premium Member
    Join Date
    Oct 2011
    Posts
    5
    Vote Rating
    0
      0  

    Default

    Same problem here. I want the following behavior for the combo: allow the user to either have blank (or delete a value if one is selected), or choose a value from the list. Is there no way to configure the behavior this way? (version 4.0.7 in case that matters).

    Update: my colleague came up with a decent workaround.
    Use the following config on the combo box (I am defining a new xtype for this but you can just do this inline as well):

    Code:
    Ext.define('Ext.ux.form.AllowBlankOrSelectCombo', {
        extend : 'Ext.form.field.ComboBox',
        alias : 'widget.allowblankorselectcombo',
        allowBlank: true,
        editable: true,
        forceSelection: true,
        typeAhead: true,
        queryMode: 'local',
        displayField: 'display',
        valueField: 'value'
    });
    Then, in the store you're using for the combo, just add a "dummy" blank record (at least this can be on the client-side only):

    Code:
    function addBlankRecordToStore(store) {
        store.add({
            display: '',
            value: ''
        });
    }
     
    var myStore = Ext.create('Ext.data.Store', {
        model: 'ValueAndDisplayModel',
        autoLoad: true,
        listeners: {
            load: addBlankRecordToStore
        },
        proxy: {
            type: 'ajax',
            url:  '/whatever/URL',
            reader: { type: 'json', root: 'dataRoot', successProperty: 'success'}
        }
    });
    This way, the user can delete the value, which will trigger a forced auto-complete, find a record in the store that has a blank value, and select that value. The only slight problem is that it affects the display of the combo box, when expanded (since there is now a small dummy record that renders at the end), but for our use case it's no big deal.

    Update 2: Apparently, I'm wrong. Some more testing reveals this actually doesn't work. Back to the drawing board.

  7. #7
    Sencha User
    Join Date
    Oct 2008
    Posts
    3
    Vote Rating
    0
      0  

    Default

    I think you're really close. I do something very similar and this approach is working for me. I have a standard combo (with forceSelection:true) populated by a REST store, to which I add an empty model in the load callback.

    Code:
    Ext.getStore("MyStore").load({
        scope   : this,
        callback: function(records, operation, success) {
            var model = Ext.create('MyModel', {
                display: '',
                value: ''
            });
            Ext.getStore('MyStore').insert(0, [model]);
        }
    });
    I should add that I had some trouble using setValue on a combo with forceSelection:true, so I'm loading the store before the combo is rendered.

  8. #8
    Touch Premium Member
    Join Date
    Oct 2011
    Posts
    5
    Vote Rating
    0
      0  

    Default

    All right, we got it working as desired. Not pretty, but it works.

    First, the definition of the custom Combo box (really a preconfigured class). It is defined as a new type so that it can be easily used in many combo boxes. The only difference between this and an inline configuration of the same (via xtype: 'combo') would be using field.initialConfig.valueField instead of field.valueField in the functions below.

    Code:
    Ext.define('Ext.ux.form.CustomCombo', {
        extend : 'Ext.form.field.ComboBox',
        alias : 'widget.customcombo',// Defining the xtype
        allowBlank: true,
        editable: true,
        forceSelection: true,
        //autoSelect needs to be false to allow the "clearing out" of a value to work properly
        autoSelect: false,
        typeAhead: true,
        displayField: 'display',
        valueField: 'value',
        queryMode: 'local',
        //define a new property to hold the last "valid" selected or auto-completed value
        //this should be initialized with the "blank" record value in the store you are configuring (empty string in this case) 
        lastValidValue: '',
        listeners: {
            select: function(field, records, eOpts) {
                //this gets fired if user clicks an item from the dropdown
                if (records && records[0]) {
                    //there is a valid selection made, capture the value
                    field.lastValidValue = records[0].get(field.valueField);
                }
            },
            blur: function(field, eOpts) {
                //this gets called when the field loses input focus
                var currentValue = field.getValue();
                //first, see whether the value entered is actually in the (now filtered) store
                var recordIndex = field.getStore().findExact(field.valueField, currentValue);
                if (recordIndex >= 0) {
                    //the current value IS in the store, so remember it as a "valid" value
                    field.lastValidValue = currentValue;
                }
                else {
                    //the current value is NOT in the store, so clear the filter, then set the value back to previously seen valid one
                    field.getStore().clearFilter();
                    field.setValue(field.lastValidValue);
                }
            }
        }
    });
    Now, defining the store to work with this. Notice autoLoad and the load listener.

    Code:
    var myComboStore = Ext.create('Ext.data.Store', {
        //DisplayAndValueModel is simply a model with 2 fields, 'display' and 'value'
        model: 'DisplayAndValueModel',
        autoLoad: true,
        listeners: {
            load: function(store) {
                store.add({
                    display: '',
                    value: ''
                });
            }
        },
        proxy: {
            type: 'ajax',
            url:  '/whatever/URL',
            reader: {type: 'json', root: 'dataRoot', successProperty: 'success'}
       }
    });
    Finally, creating an instance via the new custom type:

    Code:
    {
        xtype: 'customcombo',
        store: myComboStore,
        fieldLabel: 'Improved Combo Box'
    }

  9. #9
    Sencha User
    Join Date
    Feb 2012
    Posts
    30
    Vote Rating
    1
      0  

    Default

    Quote Originally Posted by protocyber View Post
    I have a combo box with 'forceSelection' config is set to true.

    The combo box is optional. It can be empty.

    If user choose one of the options and then re-empty the combo box, it doesn't want to be empty.

    The combo box always restores the previously selected value.

    It's ridiculous. It should be empty when user delete the value.
    I have the same problem :-(

  10. #10
    Sencha User
    Join Date
    Feb 2012
    Posts
    30
    Vote Rating
    1
      0  

    Default

    Quote Originally Posted by vietits View Post
    If you still want to empty the combo box when user delete the value, you could do it as follow:
    Code:
    Ext.create('Ext.form.field.ComboBox', {
        ...
        allowBlank: true,
        forceSelection: true,
        beforeBlur: function(){
            var value = this.getRawValue();
            if(value == ''){
                this.lastSelection = [];
            }
            this.doQueryTask.cancel();
            this.assertValue();
        }
    });
    Thanks, it works for me! (ExtJs 4.1.1)

Page 1 of 2 12 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •