Reputation: 9603
For UI purposes, when I load the array my viewModel is based on I add a new property to each object based on some other properties:
item.forEach(function (party) {
if (party.AcknowledgementDate() === null) {
party.Agreed = ko.observable(false);
}
else {
party.Agreed = ko.observable(true);
}
vm.Parties.push(party);
});
"Parties" is defined as ko.observableArray when the page starts.
The items in this array are edited in a separate UI window. When those changes are saved and the window closed, I call this function to update those values:
function updateAgreed() {
vm.Parties().forEach(function (i) {
if (i.AcknowledgementDate() === null) {
i.Agreed(false);
}
else {
i.Agreed(true);
}
});
}
This all works fine, and makes me very happy. The problem arrives when users create a new party item. We're using Breeze too, so we go off to the data service which requests entity framework create a new object of the appropriate type, then add an observable:
var lp = manager.createEntity('Party_dto'. { [an array of initial values] });
lp.Agreed = ko.observable('');
return lp;
Thanks to Breeze, this adds itself to the Parties observableArray because it's related to the same parent object. I can then call updateAgreed again to populate the Agreed observable with the appropriate value.
Logically, this work as expected - you can step through it and watch the Agreed observable of the new item be added and populated with the expected values. The problem comes in the UI - it doesn't update as having changed. Yet running the same code against an already-loaded object does cause the UI to update.
I'm stumped by this. I can't replicate it in Fiddle because we create objects in Breeze and not on the fly - and making a mock version without Breeze works perfectly. Why do my observables update on already loaded objects, but the same observable not update on a new object?
Upvotes: 1
Views: 475
Reputation: 14995
There are a few things that I see that need to be addressed. One, since you are using Breeze, take advantage of the model constructors and initializers. Wherever you are defining properties for your models, add the following code -
metadataStore.registerEntityTypeCtor(
'Party', null, partyinitializer);
function partyinitializer(party) {
party.Agreed = ko.observable(false);
}
Now all of your party entities have an agreed property that you can access. Next, make sure you aren't setting the Party's parent navigation property in the createEntity method, as that will break your binding.
var lp = manager.createEntity('Party'. { [an array of initial values] });
lp.parentParty(something); // Set the parent here
return lp;
This will make sure that before the party is bound back to the parent and shown in the view, all of the properties will be set. Then when you set the navigation property, it will show up in your view all happy-like.
Upvotes: 2