Strange behaviour mapping array to observableArray with ko.mapping.fromJS
Asked Answered
D

2

7

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

Downtoearth answered 11/3, 2012 at 17:33 Comment(3)
In Chrome's console make sure that you are looking at the unwrapped value of the observableArray myObservableArray(). It can be misleading when just printing out the observableArray itself.Grefer
As RP stated... you are just looking at the wrong value. Here is a fiddle that you can use to verify. Set a breakpoint on the ko.mapping line and type: ko.mapping.fromJS(data) and you'll see []. If you type: ko.mapping.fromJS(data)() and you see [Object, Object, Object, Object]. jsfiddle.net/jearles/y4b9e/8Bamby
Thanks guys, Chrome tricked me by printing just [] which indicates an empty array. But you are absolutely right, if I but braces behind the expression it shows the contents allright. Great to get comments so soon! Stackoverflow rocks...Downtoearth
P
1
ko.mapping.fromJS(data, {}, self.items);
Prankster answered 21/10, 2012 at 19:43 Comment(0)
N
1

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/

Narine answered 11/1, 2013 at 17:49 Comment(1)
Not using the mapping plugin worked in my case. I get an array of objects from the server and wanted to map it to an observable array. I used: self.MyObservArray(ko.utils.arrayMap(arrayfromServer, function (item) { return new BlogObject(item); }));Barham

© 2022 - 2024 — McMap. All rights reserved.