Search code examples
knockout.jsknockout-mapping-pluginknockout-2.0ko.observablearray

Knockout.JS mapping to observable vs. observableArray


I can't figure out why my ko.mapping is working fine when I'm bringing back an array (using the 'foreach' binding), but when it's a single object (using the 'with' binding) it doesn't work at all. I don't get any errors, but I also don't get any results:

function EventViewModel() {
    var self = this;
    self.events = ko.observableArray([]);
    self.singleEvent = ko.observable({});

    self.getEvents = function () {
        self.events.removeAll();
        $.ajax("/api/Event/", {
            contentType: "application/json",
            success: function (allData) {
                ko.mapping.fromJS(allData, null, self.events);
            }
        });
    }    
    self.getSingleEvent = function () {
        self.events.removeAll();
        $.ajax("/api/Event/?guid=435a666b-7913-417f-a474-dfb33d74c2ec", {
            contentType: "application/json",
            success: function (allData) {
                ko.mapping.fromJS(allData, null, self.singleEvent);
            }
        });
    }

    self.getEvents();
    self.getSingleEvent();
};
window.vm = new EventViewModel();
ko.applyBindings(vm);

I can shove the result from getSingleEvent() into an array and use 'foreach' again like this:

ko.mapping.fromJS([allData], null, self.singleEvent);

and make singleEvent an observableArray, which does work, but it seems like a cheat to me.

The JSON from getEvents() looks like this:

[{"EventId":4,"Year":2013,"StartDate":"2013-08-28T00:00:00","EndDate":"2013-09-02T00:00:00","EventGuid":"435a666b-7913-417f-a474-dfb33d74c2ec"},{"EventId":5,"Year":2013,"StartDate":"2013-06-07T00:00:00","EndDate":"2013-06-09T00:00:00","EventGuid":"615014ba-15cd-4371-8d43-04d66eb558a2"}]

and the JSON from getSingleEvent() looks like this:

{"EventId":4,"Year":2013,"StartDate":"2013-08-28T00:00:00","EndDate":"2013-09-02T00:00:00","EventGuid":"435a666b-7913-417f-a474-dfb33d74c2ec"}

Solution

  • I'm quite sure that ko.mapping does not make objects observable. Instead it makes each of the properties of an object observable. On the other hand, nothing is stopping you from just doing self.singleEvent(allData) to set the observable.