3
votes

I've posted my code here: http://jsfiddle.net/HYDU6/6/ It's a pretty stripped-down version of what I'm actually working with, but captures the essence of my problem. My view model is like so:

var viewModel = {
    objects: {
        foo: [
            { text: "Foo's initial" },
        ],
        bar: [
            { text: "Bar's initial" },
        ]
    }
}

I'm using the ko.mapping plugin and my create handler for objects instantiates Obj from objects.foo and then objects.bar, returning the resulting two items in an array. This part works fine; I use

var view = {};
ko.mapping.fromJS(viewModel, mapping, view);

My issue is updating based on new data. (i.e., getting data from the server). I have an object of new data and I attempt

ko.mapping.fromJS(new_model, mapping, view);

I suspect this is incorrect but I have not been able to get it working despite extensive searching. (Trust me, it's been days. ): Anyway, thanks for any help.

EDIT: So I've mostly figured it out - I was depending too heavily on mapping.fromJS and certain things were not being wrapped into observables. I also realized that I didn't need the create(), only the update(), as it is called after create() anyway. If you have a similar problem let me know!

1
Hi John, There are quite a few unusual things going on in your fiddle. First, when linking to the ko.mapping plugin, don't use the raw version from github, as some browsers with strict mime typing on will not allow the script to execute. Try using this version instead : //cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.3.5/knockout.mapping.js - Ryan Rahlf
Oh, thanks, it's one of my first. I'll update it. - user2501886
Next, I was a bit confused at first by your terminology. What you are calling "bindings" is more properly called "view models". A "binding" is what connects your view models to the UI, and vice versa. I'll suggest some edits to your post to clarify the question. - Ryan Rahlf
Ah, right- I changed the fiddle as well. - user2501886

1 Answers

4
votes

John,

When updating your data using ko.mapping be sure you don't create a new item. Your UI is already bound to the existing items, so you just want to update the values of the existing item properties; not create new ones. For the example you posted, you'll want to adjust your "update" method of your map to insert the new values into the correct ko.observable property, rather than creating a new object in it's place. The ko.mapping "update" method has a few different parameter lists depending on usage, with the third parameter being the target object of the map. You would want to update that object's properties.

obj.target[label].items[0].text(obj.data[label][0].text);

But, that's a bit of a mess. You'll probably want to create a second level of mappings (create / update) to handle "deep" object hierarchies like in your fiddle. For example one map for objects at the "foo/bar" level, and another call to ko.fromJS from within "update" with another map for the child Obj() objects.

After fixing that, you'll run into a couple simple binding errors that you can fix using another "with" binding, or a "foreach" binding for the child arrays.

Overall, you've just run into a couple common pitfalls, but nothing too severe. You can learn a bit more about a few of these pitfalls on my blog here : http://ryanrahlf.com/getting-started-with-knockout-js-3-things-to-know-on-day-one/

I hope this helps!