Ian Davis
Ian Davis

Reputation: 19413

How to add to an observable array using knockout mapping

I'm trying to add a json item to an observable array, and in a foreach rendering, it shows up. But when I try to access the item using item.property() syntax, it fails but only for the post-initial-binding item. Better explained with code...

Js:

var data = { colors: []};
data.colors.push({title: 'blue' });
var vm = ko.mapping.fromJS(data);
ko.applyBindings(vm);

vm.colors.push({ title: 'red' });

$("#out").html("<br/>colors are ...<br/>");
$.each(vm.colors(), function(i, clr) {
 $("#out").append(clr.title() + "<br/>");
});

Output: (note, "red" isn't spit out :/)

blue
red

colors are ...
blue

Demo: http://jsbin.com/ivacuw/7/edit

I've also tried doing vm.colors( [ { title: 'red' }] ) instead of the vm.colors.push(...), but same issue. Error of Uncaught TypeError: Property 'title' of object #<Object> is not a function

Upvotes: 1

Views: 1525

Answers (1)

Damien
Damien

Reputation: 8987

When you add the red color. The title is a string, so not a ko.observable. That's why you can't call it.

The problem doesn't occur on the blue title because you call the fromJS function that converts the blue string into ko.observable(string).

var data = { colors: []};
data.colors.push({title: 'blue'});
var vm = ko.mapping.fromJS(data);
ko.applyBindings(vm);

//fix 
vm.colors.push({ title: ko.observable('red') });
$("#out").html("<br/>colors are ...<br/>");
$.each(vm.colors(), function(i, clr) {
    $("#out").append(clr.title() + "<br/>");
});

@Ian Davis

If I understood you right. You can do that :

[...]
//vm.colors.push({ title: 'red' });
var arr = [{title:'green'},{title:'yellow'}];
ko.utils.arrayForEach(arr, function(item) {vm.colors.push(ko.mapping.fromJS(item)); });

I hope it helps.

Upvotes: 4

Related Questions