Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange behaviour mapping array to observableArray with ko.mapping.fromJS

I am trying to map an array of objects to an observableArray with the knockout mapping plugin. Somehow this seems not to work for me at all.

I just tested with Crome console to verify:

ko.mapping.fromJS( [ { x: 1, y: "test" } ] )

returns:
[]

What am I doing wrong? If I try the following

ko.mapping.fromJS( [ { x:1, y: "test" } ][0] )

returns an object containing x and y as observables...

it all works well. The only difference is that I only deliver a single object instead of an array of objects. But if I read the documentation of the mapping plugin correctly, it should be able to handle creating an observableArray out of a normal array.

Thanks for your help,
Andreas

like image 471
nttakr Avatar asked Mar 11 '12 17:03

nttakr


2 Answers

That's what it should be doing (at least in theory / documentation), but apparently that's not what it's doing. I am having same problem and I believe other too: https://groups.google.com/forum/?fromgroups=#!topic/knockoutjs/uKY84iZaxcs

The object must be:

{ "someName" : [ { x: 1, y: "test" } ] }

To stick with your object schema, you can use ko.utils.arrayMap to map object to your KO ViewModel: http://www.knockmeout.net/2011/04/utility-functions-in-knockoutjs.html

function Item(name, category, price) {
    this.name = ko.observable(name);
    this.category = ko.observable(category);
    this.price = ko.observable(price);
    this.priceWithTax = ko.dependentObservable(function() {
        return (this.price() * 1.05).toFixed(2);
    }, this);
}

//do some basic mapping (without mapping plugin)
var mappedData = ko.utils.arrayMap(dataFromServer, function(item) {
    return new Item(item.name, item.category, item.price);
});

EDIT

I did some more research on this and you CAN actually map JS array object with KO mapping, however, the after-map object is NOT going to be KO Observable Array. It will be just regular JS array object and, for that matter, you can data-bind with KO:

var bd = [ { x: 1, y: "bd test" }, { x: 2, y: "bd test 1dsf" } ];

var bdViewModel = ko.mapping.fromJS(bd);

// 'bdViewModel' is NOT KO Observable Array, so you can't use KO Binding. However, all the properties of 'bdViewModel' (x and y) are KO Observable.
//ko.applyBindings(bdViewModel, $("#bd").get(0));
console.log(bdViewModel());

// 'bdViewModel' must be called as function (with open and close parentheses) to see the data.
$.each(bdViewModel(), function (i, d) {
  $("#bdList").append("<li>" + d.y() + "</li>");
});

Here's the JSBin for comparison of mapping JS array and JSON: http://jsbin.com/uzuged/5/

like image 86
stack247 Avatar answered Oct 19 '22 22:10

stack247


ko.mapping.fromJS(data, {}, self.items);
like image 20
Yasin Kilicdere Avatar answered Oct 19 '22 23:10

Yasin Kilicdere