When an element is created, Knockback provides functions to auto-release ViewModels using Knockout's dispose node callback:
# binds a callback to the node that releases the view model when the node is removed using ko.removeNode ko.utils.domNodeDisposal.addDisposeCallback(node, -> kb.release(view_model) );
// binds a callback to the node that releases the view model when the node is removed using ko.removeNode ko.utils.domNodeDisposal.addDisposeCallback(node, function() { kb.release(view_model)} );
There are three ways to do this in Knockback:
# Auto-released Template el = kb.renderTemplate('template_name', view_model, options) # OR: When applying bindings kb.applyBindings(view_model, el) # OR: Manually kb.releaseOnNodeRemove(view_model, el)
// Auto-released Template var el = kb.renderTemplate('template_name', view_model, options); // OR: When applying bindings kb.applyBindings(view_model, el); // OR: Manually kb.releaseOnNodeRemove(view_model, el);
This means you can use a Backbone.Router as follows and not need to explicitly call kb.release() because ko.removeNode calls it for you:
window.RouterBackboneJS = Backbone.Router.extend({ constructor: -> Backbone.Router.prototype.constructor.apply(@, arguments) loadPage = function(el) { ko.removeNode(@active_el) if @active_el $('body').append(@active_el = el) $(el).addClass('active') } @route('', null, -> loadPage(kb.renderTemplate('home', new HomeViewModel()))) @route('things', null, -> loadUrl(kb.renderTemplate('things_page', new ThingsPageViewModel()))) @route('things/:id', null, (id) -> loadPage(kb.renderTemplate('thing_page', new ThingCellViewModel(things_collection.get(id))))) })
window.RouterBackboneJS = Backbone.Router.extend({ constructor: function() { var _this = this; Backbone.Router.prototype.constructor.apply(this, arguments); var loadPage = function(el) { if (_this.active_el) {ko.removeNode(this.active_el); } $('body').append(_this.active_el = el); $(el).addClass('active'); } this.route('', null, function() { loadPage(kb.renderTemplate('home', new HomeViewModel())); }); this.route('things', null, function() { loadPage(kb.renderTemplate('things_page', new ThingsPageViewModel())); }); this.route('things/:id', null, function(id) { loadPage(kb.renderTemplate('thing_page', new ThingCellViewModel(things_collection.get(id)))); }); } });