This is a migrated thread and some comments may be shown as answers.

ComboBox MVVM binding entire object instead of object value(MVVM Bug)

14 Answers 813 Views
ComboBox
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Paul
Top achievements
Rank 1
Paul asked on 26 Jun 2012, 11:31 PM
I have a ClientListItem javascript prototype with several fields such as "ClientName" and "ClientID". I have a list of these objects in a viewmodel datasource called "BrokersDatasource". It is a property of a kendo observable.

In the HTML markup I declare the combobox and bind it to the datasource with the following
<input
id="viewRequest_drpBroker"
data-role="combobox"
data-text-field="ClientName"
data-value-field="ClientID"
data-bind="source: BrokersDatasource, value: InspectionRequest.BrokerID"
/>

The list is populated correctly, the datasource is bound, the proper text appears, however the ClientID is not being bound as the value. On selection of a combobox item I am expecting the ClientID to be reflected in the viewmodels InspectionRequest.BrokerID. However instead of setting the ClientID, it is setting the entire ClientListItem instance to the BrokerID. So the actual BrokerID value is something like '{ClientName: "Generic Broker", ClientID: "44"}', when in fact it should just be "44".

The issue only occurs one way. If I set the BrokerID using viewmodel.set("InspectionRequest.BrokerID", 44), it will find and toggle the correct list item and text in the widget. However when selecting from GUI/Widget it sets the BrokerID to entire instance of the object instead of just numeric value.

The bug is present in both the latest commercial release(2012.1.515) and latest internal build(2012.1.615). I have used autocomplete and dropdownlists in a similar way with no issues encountered.


14 Answers, 1 is accepted

Sort by
0
Paul
Top achievements
Rank 1
answered on 26 Jun 2012, 11:39 PM
I'd like to make a correction to my last statement. The issue does exist in dropdownlists as well. My former dropdownlist implementations were slightly different until now. However when using MVVM selecting from dropdown list sets object instead of object value. So the bug could be part of some shared logic between dropdownlists/comboboxes.

I will continue stepping through the Javascript to see what I find.
0
Paul
Top achievements
Rank 1
answered on 27 Jun 2012, 12:16 AM

I found the section of code that is changing the value. It is in the "kendo.binder.js" file

change: function() {
                var value = this.widget.value();
                var idx, length;
  
                var field = this.options.dataValueField || this.options.dataTextField;
  
                if (field) {
                    var source,
                        isObservableObject = this._valueIsObservableObject;
  
                    if (this.bindings.source) {
                        source = this.bindings.source.get();
                    }
  
                    if (value === "" && isObservableObject) {
                        value = null;
                    } else {
                        if (!source || source instanceof kendo.data.DataSource) {
                            source = this.widget.dataSource.view();
                        }
  
                        for (idx = 0, length = source.length; idx < length; idx++) {
                            if (source[idx].get(field) == value) {
                                if (isObservableObject) {
                                    value = source[idx];
                                } else {
                                    value = source[idx].get(field);
                                }
                                break;
                            }
                        }
                    }
                }
  
                this.bindings.value.set(value);
            }

On the first line "var value = this.widget.value();" it is finding the correct value of the drop down list.

However inside the for loop it is reassigning the value to the instance of the selected datasource item, instead of the items value.
if (isObservableObject) { 
        value = source[idx]; 
}

Please correct this bug in next internal build, or please advise if my implementation is incorrect.
0
Atanas Korchev
Telerik team
answered on 27 Jun 2012, 06:49 AM
Hello Paul,

 This is actually not a bug. This behavior is by design. The value binding will use the whole object which is currently selected in the combobox not just the value field. We can't change this behavior because quite a lot of customers currently rely on it.

Regards,
Atanas Korchev
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Paul
Top achievements
Rank 1
answered on 27 Jun 2012, 11:39 AM
I am confused about the purpose of the data-value-field property then. Since during the MVVM binding/set process it does not fulfill any purpose. If this is not a bug then it creates an inconsistency in the Kendo framework. If I can set the numeric value using observable.set() and see the widget reflect the change, then that functionality should also work both ways or none at all.

In the case you want to bind an entire instance rather than just the value, then the data-value-field should be omitted or it should require a keyword such as self/this. It makes logical sense that the data-value-field would become the value... So beyond an inconsistent two way behaviour there is an ambiguous naming convention.

Breaking changes get implemented all the time, this would be a justified situation and if the logic cannot change then an enhancements should be added to allow binding of the value field using a different property name.

If you already have an alternative method of binding where I can bind only the value field, please advise.


0
Atanas Korchev
Telerik team
answered on 27 Jun 2012, 11:56 AM
Hello Paul,

 The data-value-field is required to determine which object should the selected value point to. There is a workaround to have the value be the "data-value-field" itself. The workaround is to set the initial value to some primitive type: string, number. Here is a demo: http://jsfiddle.net/korchev/DWUnx/4/ 

Regards,
Atanas Korchev
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Paul
Top achievements
Rank 1
answered on 27 Jun 2012, 01:02 PM
The value I am setting corresponds to a Nullable Int32 in a WCF Web Service.

Using the proposed work around there are 4 issues.
1. Default value cannot be null, which is required.
2. When combo box is cleared it defaults value to an empty string which is not a supported numeric type and will cause deserialization to fail. Value must be null or numeric.
3. Initializing with a numeric value such as 0, will print the value in the textbox since it does not exist in the list.
4. Placeholders will not work

I think this should be a configurable option, rather than initializing with a null/notnull variable.

Here are some suggestions:
1. Add new widget property which allows to specify empty value. Instead of just placeholder you would instead have placeholder-text, and placeholder-value. So you can choose null, empty string, 0, etc.... This takes care of nullable types.
2. Allow override of IsObservable so that in the markup you can specify to bind a value instead of observable object.




0
Atanas Korchev
Telerik team
answered on 27 Jun 2012, 01:27 PM
Hello Paul,

 I am afraid that we cannot suggest any immediate workaround than the one from my previous reply. We also can't change the implementation overnight without breaking existing customer's applications.

 I suggest you open a new user voice item to request a change in this behavior. We will act according to the number of votes this feature gets.

Greetings,
Atanas Korchev
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Gary
Top achievements
Rank 1
answered on 12 Dec 2012, 08:02 PM
Hi paul, you have probably solved this by now but I had the same issue.

My solution was to bind a change handler and set the value to the field of the object I wanted.
It's not pretty, but it worked ok.
myModelVariable.bind("change", function (e) {
            // Drop down lists return the entire object as the value
            // but that is not what we want in the field. Just the dataValue field is required
            if (e.field == "MyModelFieldName") {
                var val = myModelVariable.get(e.field);
                // Do not use Set mothod as this will fire this event again!
                if (!(typeof val === 'undefined')) {
                    myModelVariable.MyModelField = val.MyValueFieldValue;
                }
            }
        });
0
Paul
Top achievements
Rank 1
answered on 16 Jan 2013, 03:58 PM
Thanks Gary. Yes I did create workaround, it is actually similar to yours. Didn't really have any other choice. I actually ran into the problem again today, and I forgot I created this thread lol.

I never did end up creating a User Voice thread, it seems a bit ridiculous that paying customers get the same voting power as everyone else. So much for premium support!

Anyway, it looks like someone else posted a UserVoice thread for this exact issue and it has 35 votes.
http://feedback.kendoui.com/forums/127393-kendo-ui-feedback/suggestions/3356384-dropdown-null-values

Telerik releases breaking changes all the time, especially with reports. This is a relatively small change in comparison, so I don't see why there is so much reluctance. Anyway I don't have the patience to argue the point anymore, just going to stick with the workaround. 
0
Dan
Top achievements
Rank 1
answered on 24 Apr 2013, 06:50 PM
Atanas-

I came across this thread looking into a similar problem and I'm curious about this behavior.  You listed the jsFiddle at http://jsfiddle.net/korchev/DWUnx/4/ and based on that I modified it to this one: http://jsfiddle.net/danielrdevine/4zEAY/2/

I'm confused about the behavior in my version.  I understand that you end up with the whole object bound for items 1 and 2, but why not for the null one?  In my application, we were relying on something similar to the selectedProductID.id property holding the value, but we don't get an object with id = null, we get a null in place of the object and selectedProductID.id is undefined.  It's like a weird combination of the 2 modes (binding to the object vs. value).  Thanks in advance for any clarity you can provide.
0
Atanas Korchev
Telerik team
answered on 25 Apr 2013, 07:23 AM
Hi,

 I updated the fiddle to the latest version (it was two versions behind) and it seems to work better: http://jsfiddle.net/4zEAY/3/

Regards,
Atanas Korchev
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Dan
Top achievements
Rank 1
answered on 25 Apr 2013, 12:47 PM
Atanas-

That does look better in one way I hadn't really noticed.  When you go back to selecting the null value it puts the correct -Select- text in the box instead of null.

However, it appears that the odd behavior persists even in the new version (which, by the way is what I'm developing on, didn't notice it was an older version in the fiddle).  You can see what I mean by binding the span to selectedProductID instead of selectedProductID.id.  When you do that, you'll see the objects for the Food and Drinks products, but when you select the null one, you just get a null and not an object with an id of null.

I think this illustrates it: http://jsfiddle.net/danielrdevine/T48WH/1/
0
Atanas Korchev
Telerik team
answered on 25 Apr 2013, 01:03 PM
Hi,

 This doesn't work because the combobox's value is always a string. In this case the value is the string "null". Since "null" != null it cannot find the right value from the products array. It works with numbers because "1" == 1 in JavaScript.

I have two suggestions
- use a different value for the - Select- item - for example 0. 
- avoid having an extra item altogether and rely on the combobox' placeholder: http://jsfiddle.net/T48WH/2/

All the best,
Atanas Korchev
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Dan
Top achievements
Rank 1
answered on 25 Apr 2013, 02:33 PM
Atanas-

Ok, I think I understand now.  It's a bit confusing how it binds either the object or the specific value inside the object based on the initial value, especially in the null != "null" case (didn't realize it was always comparing to a string version).  Thanks for the clarification.
Tags
ComboBox
Asked by
Paul
Top achievements
Rank 1
Answers by
Paul
Top achievements
Rank 1
Atanas Korchev
Telerik team
Gary
Top achievements
Rank 1
Dan
Top achievements
Rank 1
Share this question
or