I have the following view model, used for editing Person objects in an HTML form:
function PersonModel(person) {
var self = this;
self.id = ko.observable(person.Id);
self.firstName = ko.observable(person.FirstName);
self.surname = ko.observable(person.Surname);
self.email = ko.observable(person.Email);
self.cell = ko.observable(person.Cell);
self.save = function (data) {
savePerson(data);
};
}
When the user wants to edit a Person, I bind a new instance of this to an edit form, like this:
function editPerson(person) {
var url = "@Url.Action("EditJson", "Person")";
$.getJSON(url, function (data) {
$("#person-detail").css("display", "block");
ko.applyBindings(new PersonModel(data), $("#person-detail")[0]);
});
}
And in the form I bind a click event to the save method in the view model:
<a href="#" data-bind="click: save">Update</a>
I now have a problem of multiple DB updates being run when I edit a single person record, and I assume this is because I have called applyBindings more than once on the same element, the edit popup. I can sort of confirm this as I have as many DB edits execute as times I call ApplyBindings.
Now I either need to know how to remove bindings applied by applyBindings, or how to only apply bindings once, and update my view model instead of recreating it for each edit. I would much prefer the first approach. A view model should not exhibit singleton characteristics.
Ryan’s solution is the best for most situations. If you’re truly dealing with a module of JS and HTML code that can be instantiated multiple times on a page, you might want to look into
ko.cleanNode()orko.removeNode().Both of those methods are used internally by KO to handle memory leaks and binding cleanup. In a recent project, I have a table with several dynamically added rows of products. Each one of those products has to be editable inline. Instead of duplicating the form html for each row, I opted to setup a sort of KO module pattern where the html is dynamically loaded into the table row, bindings are applied, and bindings are removed once you’re done editing.
Here’s the basic AMD module I inherit from:
It uses Ryan’s KO classBindingProvider which you can find here:
https://github.com/rniemeyer/knockout-classBindingProvider