3

Perhaps I'm misunderstanding the concept of Kendo's MVVM implementation, but... I have a simple Kendo UI Mobile view that is data-bound to a view model:

var myViewModel = kendo.observable({
    myEntity: null,

    onViewShow: function (e) {
        var bindingEntity = myStaticDataSource[0];
        myViewModel.set("myEntity", bindingEntity);
    }
});

myStaticDataSource is a static array of "entities" as simple JavaScript objects, with fields like name or description.

The view and its input fields are bound to the view model:

<div data-role="view" data-layout="default" data-model="myViewModel" data-bind="events: { show: onViewShow }">
    <form>
        <ul data-role="listview" data-style="inset">
            <li>
                <label>
                    Name
                    <input type="text" data-bind="value: myEntity.name" />
                </label>
            </li>
        </ul>
    </form>
</div>

When the user changes the input field, the corresponding field (e.g. name) is updated in the data-bound view model entity myEntity. But: what I would have expected is that the entity in myStaticDataSource is updated as well, since I'm not cloning objects. But it isn't! Its value remains on the original value. Why is this? Am I missing something about Kendo's MVVM handling?

Matthias
  • 3,403
  • 8
  • 37
  • 50
  • You _are_ cloning it by assigning the element to a variable using `var bindingEntity = myStaticDataSource[0]` and then binding that variable to the view. It's doing exactly what you told it to. The variable `bindingEntity` (i.e. `myEntity`) is being updated, not `myStaticDataSource`. – Brett Oct 15 '14 at 13:44
  • 1
    @Brett that is not quite true. `var bindingEntity = myStaticDataSource[0]` does not clone the item, the call to kendo `.set()` does as a side-effect. – CodingWithSpike Oct 15 '14 at 13:57

1 Answers1

5

This is a side-effect of Kendo Observable objects and arrays. When you assign a property to an ObservableObject using the .set() method, it wants to make that assigned item an observable as well. Your items in myStaticDataSource are probably plain JS objects and not Kendo Observables, so Kendo wraps the object into a new ObservableObject for you. This means that the objects are no longer the same.

This might make more sense:

var items = [{name: "item one"}];
var vm = kendo.observable({item: undefined});
vm.set("item", items[0]);
vm.item === items[0]; // returns FALSE
items[0] instanceof kendo.data.ObservableObject // returns FALSE
vm.item instanceof kendo.data.ObservableObject // returns TRUE


var items = kendo.observable([{name: "item one"}]);
var vm = kendo.observable({item: undefined});
vm.set("item", items[0]);
vm.item === items[0]; // returns TRUE
items[0] instanceof kendo.data.ObservableObject // returns TRUE
vm.item instanceof kendo.data.ObservableObject // returns TRUE

The "fix" for this is to do any one of:


Make myStaticDataSource a Kendo DataSource, which will make all the items you put into it a ObservableObject.

var myStaticDataSource = new kendo.data.DataSource({
    data: [
        {name: "Bob"}
    ]
};

Make myStaticDataSource a Kendo ObservableArray, which will make all the items you put into it a ObservableObject

var myStaticDataSource = kendo.observable([
    {name: "Bob"}
]);

Make each item in the myStaticDataSource array an ObservableObject

var myStaticDataSource = [
    kendo.observable({name: "Bob"})
];
CodingWithSpike
  • 42,906
  • 18
  • 101
  • 138
  • Thanks! I didn't know that the call of `.set()` has the side effect of cloning the object. Now it's clear! – Matthias Oct 15 '14 at 17:53