I asked this question previously, but it didn't get much response. It was obvious that I wasn't very clear what I was trying to achieve, so I'll try again.
Here's the jsFiddle to play around with
I'm working on an app that will (at an interval) call a web method, which will read a database and build up a JSON string to return which is used to construct my view model. When my view model changes I need to mutate all selected observables with the new data.
Take this as an example underlying model.
var model = {
people: [
{ forename: "Test", surname: "Person", numbers: [1,2,3] },
{ forename: "Another", surname: "Test", numbers: [4,5,6] }
]
};
Simple enough, a table of people that when a row is clicked on a modal will pop up showing a list of numbers
the selected person has. While this modal is open, the data could be being updated behind the scenes so if [Test Person] is selected (and the modal pops up) and someone, somewhere adds [7,8,9]
to their numbers
then I need the modal to refresh showing these additions.
Here's a basic view model (using ko.mapping
for brevity):
var viewModel = {
people: ko.mapping.fromJS(model.people),
selectedPerson: ko.observable(null),
refresh: function () {
ko.utils.arrayForEach(model.people, function (person) {
var last = person.numbers[person.numbers.length - 1];
var newNumber = last + 1;
person.numbers.push(newNumber);
});
ko.mapping.fromJS(model.people, this.people);
console.log(ko.toJSON(this));
}
};
When a row is clicked on, the person is stored in selectedPerson
which makes my modal become visible in the UI (I'm using Zurb Foundation):
<div id="modal" class="reveal-modal" data-bind="if: selectedPerson">
This modal shows a table of numbers
with a button named Update Observable - this calls a function to emulate the changes to the underlying model (in this case I'm taking the last item in numbers
incrementing it by 1 and pushing it on). When this is done I then re-create my view model (using ko.mapping
for brevity) and expect everything on the UI to be updated to reflect the change - all fine apart from the modal.
Looking at the JSON of my view model after re-mapping I can see that the view model has been updated correctly, but the selectedPerson
hasn't. I assumed selectedPerson
was a reference, not a copy, but I obviously assumed wrong and we end up with this.
{
"people": [
{
"forename": "Test",
"surname": "Person",
"numbers": [1,2,3,4,5,6,7,8]
},
{
"forename": "Another",
"surname": "Test",
"numbers": [4,5,6,7,8,9,10,11]
}
],
"selectedPerson": {
"forename": "Test",
"surname": "Person",
"numbers": [1,2,3]
}
}
So I suppose my question is: how do I update selectedPerson
(or in fact any other selected observable there may be) when the underlying model changes?