Results 1 to 7 of 7

Thread: ComboBox.setValue behavior with values not in store

    You found a bug! We've classified it as a bug in our system. We encourage you to continue the discussion and to find an acceptable workaround while we work on a permanent fix.
  1. #1
    Ext JS Premium Member meditecsports's Avatar
    Join Date
    Oct 2010
    Location
    Germany
    Posts
    48

    Default ComboBox.setValue behavior with values not in store

    While migrating from ExtJS3->4, I discovered, that setValue() on ComboBoxes behave different than expected. When using it's setValue() method to put (database) values into it, it checks whether these values are in the associated store. If not, a "valueNotFoundText" is used or it is set blank.

    ExtJS3 just sets the value, regardless if it is in the store or not.

    The thing is:
    ComboBoxes are also used, just to make "recommendations" to the user (based on the store) and the user may enter something else (not in the store). This should be the case, when the ComboBox config property "forceSelection" is set to false. Then, I want setValue() just to accept all values.
    If "forceSelection" is set to true, the current behavior is ok.

    I know, I could use setRawValue(), but then I have to check whether this is a ComboBox and if it has it's forceSelection flag not set. Sounds like a bad idea to me...

  2. #2
    Sencha User mberrie's Avatar
    Join Date
    Feb 2011
    Location
    Bangkok, Thailand
    Posts
    506

    Default

    You might be interested in this discussion:

    http://www.sencha.com/forum/showthre...cord-in-a-form

  3. #3
    Ext JS Premium Member meditecsports's Avatar
    Join Date
    Oct 2010
    Location
    Germany
    Posts
    48

    Default

    Thanks for your reply!

    Unfortunately this does not help, because my case has nothing to do with incomplete loaded stores and delaying the setValue() call.

    It's is about having ComboBox values, that are not in a store and never will be. The store contains only suggestions for these values.

    ...and if something else comes back from the database, the ComboBox stays empty!

  4. #4
    Sencha User
    Join Date
    Jun 2009
    Location
    Heidelberg, Germany
    Posts
    78

    Default

    In http://www.sencha.com/forum/showthre...l=1#post605974 mberrie points out:

    I assume that setValue applies those restrictions (not set a display value when there is no matching record) because it requires data to be provided in order to allow rendering the display value via the displayTpl (see getDisplayValue() ).
    ComboBox in 4.x defines a displayTpl that is used to render the display value. From the code it seems like this might be intended to be a config option, although it is not mentioned in the docs.

    To be able to use the displayTpl, the store needs to provide a record. So to use setValue() requires the value to be in the store. At first it seemed counter-intuitive to me when forceSelection is turned off, but in a way it makes sense, because setValue sets the value, not the display. valueField and displayField may be different.

    typeAhead uses setRawValue, too. And there is a beforeBlur-method that calls assertValue() if forceSelection is true. Of course this only applies if the focus was on the field before, so it doesn't apply in your case of setting the value from outside.

    From what I understand, you are trying to set a value that is not in the store, so in any case this should only work if forceSelection is false, so for your code to work you will need to check for forceSelection anyway, won't you?

  5. #5
    Sencha User mberrie's Avatar
    Join Date
    Feb 2011
    Location
    Bangkok, Thailand
    Posts
    506

    Default

    EDIT: Didn't see Kleins' post, so removed mine to keep the discussion concise.

  6. #6
    Sencha User mberrie's Avatar
    Join Date
    Feb 2011
    Location
    Bangkok, Thailand
    Posts
    506

    Default

    The problem with the current implementation of ComboBox#setValue is that it doesn't consider all possible scenarios/configurations.

    The problem of rendering the display value without the associated/selected record loaded is actually only an issue when the displayed value of the field is different from the actual field value.

    In the simplest of ComboBox setups where the 'displayField' equals the 'valueField' and/or any custom displayTpl does not reference any other field than the 'valueField', it is actually no problem to render the correct value in the ComboBox text field - even if the associated/selected record is not available.


    And this is the use-case that meditecsports describes in his opening post.



    I created the following test case which showcases two different scenarios:

    Use-case A: a ComboBox is used in a typical many-to-one (aka Ext's belongsTo) relationship. The ComboBox' valueField is the foreign key, the displayField might be any other, hence displayField != valueField.
    I can think of two different reasons why a value passed to setValue might not match a record in the underlying store:

    1. the store is not loaded yet (that is the use-case that has been considered in Ext4)
    2. the store has been successfully loaded but does not contain the selected record, because the result from the query to the server is limited by the maximum number of items (paging), and the selected record was dropped from the resultset (this is the scenario that Kleins describes in his thread if I understand him correctly)


    Use-case B: a ComboBox where the ComboBox is used to show possible (maybe frequently used) string values, but the field can hold any arbitrary string value entered by the user. displayField == valueField.

    Code:
    <html>
    <head>
        <title></title>
        <meta http-equiv="content-type" content="application/xhtml+xml; charset=utf-8"/>
        <link rel="stylesheet" type="text/css" href="ext/resources/css/ext-all.css"/>
        <style>
            body {
                padding: 50px;
            }
    
            .activity-panel {
                width: 400px;
            }
    
            .activity-panel > .x-panel-body {
                padding: 20px;
            }
        </style>
        <!--<script type="text/javascript" src="ext/bootstrap.js"></script>-->
        <script type="text/javascript" src="ext/ext-debug.js"></script>
        <script type="text/javascript">
            Ext.Loader.setConfig({
                enabled: true,
                disableCaching: true,
                paths: {
                    'Ext': 'ext/src'
                }
            });
    
            /**
             * In this example we use a simple data model inspired by a scenario taken from a CRM application:
             * A sales represantative tracks any interactions with his customers: those so-called 'Activities' involve
             * a 'Customer' and occur on a specific 'Date' and will be filed with a short 'Description'.
             *
             * ComboBox use-case A:
             * An Activity references the associated Customer by its foreign key. In terms of ComboBox configuration
             * this means that displayField != valueField.
             *
             * ComboBox use-case B:
             * Each Activity has a Description. The user can enter any text, but the ComoBox is used to suggest commonly
             * used values. This is not a foreign-key relationship, displayField == valueField
             */
            Ext.define('Activity', {
                extend : 'Ext.data.Model',
                fields : [
                    { name : 'date', type : 'date' },
                    { name : 'description', type : 'string' },
                    { name : 'customer', type : 'int' }
                ]
            });
    
            // this is for ComboBox use-case A where displayField!=valueField
            // any 'Activity' references a 'Customer' via a one-to-many relationship
            Ext.define('Customer', {
                extend : 'Ext.data.Model',
                fields : [
                    { name : 'id', type : 'int' },
                    { name : 'name', type : 'string' },
                    { name : 'city', type : 'string' },
                    { name : 'state', type : 'string' }
                ]
            });
    
            // this is for ComboBox use-case B where displayField=valueaField
            // this is no real relationship in the data model, the ActivityType is
            // merely a list of commonly used values that *might* be used
            Ext.define('ActivityType', {
                extend : 'Ext.data.Model',
                fields : [
                    { name : 'description', type : 'string' }
                ]
            });
    
            Ext.onReady(function() {
                var customerStore = Ext.create('Ext.data.Store', {
                    model : 'Customer',
                    data : [
                        /*sample data from http://www.briandunning.com/*/
                        { id : 1, name : 'Essie Vaill', city : 'Anchroage', state : 'AK' },
                        { id : 2, name : 'Cruz Roudabush', city : 'Phoenix', state : 'AZ' },
                        { id : 3, name : 'Billie Tinnes', city : 'New York', state : 'NY' }
                    ]
                });
    
                var activityTypes = Ext.create('Ext.data.Store', {
                    model : 'ActivityType',
                    data : [
                        { description : 'Online Webinar'},
                        { description : 'Video Conference'},
                        { description : 'Telephone Call'},
                        { description : 'Lunch/Dinner'}
                    ]
                });
    
                // activity referencing a customer who is NOT in the store (and therefore not in the dropdown list)
                var activityWithMrWho = Ext.ModelManager.create({
                    date : '12/12/2011',
                    description  : 'Discussed important buisness at the local beer bar',
                    customer: 666
                }, 'Activity');
    
                // activity referencing a customer who is included the store/list
                var activityWithMrVaill = Ext.ModelManager.create({
                    date : '01/01/2011',
                    description  : 'Online Webinar',
                    customer: 1
                }, 'Activity');
    
                // the combobox
                var comboA = Ext.widget('combobox', {
                    name : 'customer',
                    fieldLabel : 'Customer',
                    queryMode : 'local',
    
                    store : customerStore,
                    displayField : 'name',
                    valueField : 'id',
                    autoSelect : false,
                });
    
                var comboB = Ext.widget('combobox', {
                    name : 'description',
                    fieldLabel : 'Activity',
                    queryMode : 'local',
    
                    store : activityTypes,
                    displayField : 'description',
                    valueField : 'description',
                    autoSelect : false
                });
    
                // the button handler that loads a record that is not included in the store/list
                function loadMrWho() {
                    var form = this.up('form').getForm();
                    form.loadRecord(activityWithMrWho);
                }
                // the button handler that loads a listed record
                function loadMrVaill() {
                    var form = this.up('form').getForm();
                    form.loadRecord(activityWithMrVaill);
                }
    
    
                // the panel
                Ext.create('Ext.form.Panel', {
                    renderTo : 'target',
                    title : 'Activity Form',
                    layout : 'anchor',
                    cls : 'activity-panel',
                    defaults : {
                        anchor : '100%'
                    },
                    items : [
                        {
                            xtype : 'datefield',
                            name : 'date',
                            fieldLabel : 'Date',
                            width : '100px',
                            anchor : ''
                        },
                        comboB,
                        comboA
                    ],
    
                    buttons: [
                        {
                            text : 'Load Mr Who',
                            handler : loadMrWho
                        },
                        {
                            text : 'Load Mr Vaill',
                            handler : loadMrVaill
                        }
                    ]
                });
            });
        </script>
    
    </head>
    <body>
    <div id="target">
    
    </div>
    </body>
    </html>

  7. #7
    Sencha User mberrie's Avatar
    Join Date
    Feb 2011
    Location
    Bangkok, Thailand
    Posts
    506

    Default

    Just wanted to update this thread to point out that this bug is a duplicate of

    http://www.sencha.com/forum/showthre...s-in-empty-val

    and has been fixed meanwhile in an release > 4.0.2a.


    Unfortunately we didn't keep going on this thread to pin down the problem, otherwise the bug might have been fixed in 4.0.2a already.

Posting Permissions

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