I've got my root knockout model that holds a collection of VisitEntries, each of these entries has an object on it called RoomProfile. When a user creates a visit entry (adds a room to their visit list), the room's profile data should be loaded and displayed to the user inside that collection. But I can't update the associated model. I've done this before in other areas no problem. I think there is a problem because I am making a copy of VisitEntryToAdd
on my root mappedModel
, or because it's inside a collection. I'm not sure, but those are the only differences from other times when I've done this.
mappedModel.addVisitEntry = function () {
var visitEntryToAdd = ko.mapping.fromJS(ko.mapping.toJS(mappedModel.VisitEntryToAdd));
$.ajax({
url: '/GetRoomProfileForVisit',
type: 'POST',
data: ko.mapping.toJSON({ Id: visitEntryToAdd.SelectedRoom.Id() }),
dataType: "json",
contentType: 'application/json; charset=utf-8',
success: function (data) {
if (data !== null) {
console.log("Checking entry before assigning room profile data: \n" + ko.mapping.toJSON(visitEntryToAdd));
console.log("Room Profile Data Loaded:\n" + ko.mapping.toJSON(data));
ko.mapping.fromJS(data, {}, visitEntryToAdd.RoomProfile);
console.log("Checking entry after assigning room profile data: \n" + ko.mapping.toJSON(visitEntryToAdd));
}
mappedModel.VisitEntries.push(visitEntryToAdd);
}
});
}
Going through the above code:
First console.log shows that visitEntryToAdd
has all the correct fields including RoomProfile
which it set to null before I add the room profile data.
Second console.log confirms my ajax method did return data and it is appropriately formed.
Third console.log shows that same visitEntryToAdd
, and RoomProfile
on it is still null.
I was able to get this working by doing:
visitEntryToAdd.RoomProfile(ko.mapping.fromJS(data));
But I am not sure why it doesn't work using the fromJS
command only, as that it's usage. If someone can provide an explanation I will mark that as the answer.
If visitEntryToAdd.RoomProfile
is null before the mapping, you are effectively saying ko.mapping.fromJS(data, {}, null)
and there is nothing tying the newly mapped data to the viewmodel.
You can solve this by initializing RoomProfile
on the visit entry to {}
instead of null
, or executing the mapping as:
ko.mapping.fromJS({RoomProfile: data}, {}, visitEntryToAdd);
This way mapping will begin from the root of the viewmodel and the RoomProfile
field on it is assignable. If it makes sense to initialize the field to {}
instead, it will work because the RoomProfile
field on the viewmodel is not replaced, only fields on it are updated and so the link from visitEntryToAdd -> RoomProfile is preserved.