Reputation: 6020
Note: I'm currently learning with KnockoutJS so any guidance on best practices, or corrections on whether I'm doing things right are always appreciated!
I am working on a test project trying to get to grips with the brilliant KnockoutJS and I'm now at a point where I need to think about deferring the update of my observableArray
. I have a view model of items (which I'm retrieving via an AJAX call), and a table that lists them. When I click on an item, a modal pops up populated with the details and allows me to edit them. Let's just call them items for now, here's the definition.
var itemViewModel = function (id, name) {
this.Id = ko.observable(id);
this.Name = ko.observable(name);
};
When I click on the item, I set a selectedItemId
and then loop through my items looking for the correct one, when found I set it to selectedItem
and show the modal.
var targetItem = ko.utils.arrayFirst(self.items(), function (current) {
return current.Id() === self.selectedItemId();
});
self.selectedItem(targetItem);
All working perfectly so far, but my observableArray
is getting updated irrespective of whether I click Close or Save in the modal. Now, I'm aware this is correct behavior, but my question is: how do I update my observableArray
ONLY when I click Save?
Here's how I think I should be doing it (but I'm not entirely sure whether I'm correct).
I should have a non-observable version of itemViewModel
(still extracted from the items
collection as before, but without the observables) and then call some event when I click Save on the modal that replaces the item in the observableArray
like so:
self.items.replace(oldItem, newItem);
While the above does seem logical, I'm not sure if it makes full use of KnockoutJS or not. The main thing that irks me about the above, is having to have the non-observable version of itemViewModel
, can I not just unsubscribe or dispose the tracking?
Upvotes: 2
Views: 225
Reputation: 6020
A huge thanks to the article provided by nemesv, which gave me all I need to do exactly what I wanted to do! For anyone else stumbling on this with the same question, here's what I did.
I used the protectedObservable
that was defined in this article and followed his example of committing and rolling back changes. So I defined my itemViewModel
like this:
var itemViewModel = function (id, name) {
this.Id = ko.protectedObservable(id);
this.Name = ko.protectedObservable(name);
this.commit = function () {
this.Id.commit();
this.Name.commit();
};
this.rollback = function() {
this.Id.reset();
this.Name.reset();
};
};
Then applied the same two commit
and rollback
methods to my overall view model (which just invoke the $parent.commit
and $parent.rollback
methods on the event of clicking Save like this:
var viewModel = function (items) {
var self = this;
self.items = ko.observableArray(items);
self.selectedItemId = ko.observable();
self.selectedItem = ko.observable();
self.selectItem = function () {
var targetItem = ko.utils.arrayFirst(self.items(), function (current) {
return current.Id() === self.selectedItemId();
});
self.selectedItem(targetItem);
$('#edit-item-modal').dialog('open');
};
self.commit = function () {
self.selectedItem().commit();
$('#edit-item-modal').dialog('close');
};
self.rollback = function () {
self.selectedItem().rollback();
$('#edit-item-modal').dialog('close');
};
};
I really like this solution, so thanks again to nemesv for the information!
Upvotes: 1