2

I have a div where I use knockout bindings. For example,

<div id='my_div'>
  <span data-bind="text: dialog_body"></span> 
</div>

So, the knockout binding is:

var viewmodel=function(){
 this.dialog_body = 'Some text';
};
ko.applyBindings(new viewmodel(),$("#my_div")[0]);

Now the question is: if I call $('#my_div').remove(); will this also remove the knockout binding or should I be worried about memory leak?

faisal
  • 1,327
  • 10
  • 19
  • 1
    jQuery does not know about KO and KO doesn't care about jQuery. See [cleanNode as discussed here](http://stackoverflow.com/questions/15063794/can-cleannode-be-used-to-clean-binding) or [here](http://stackoverflow.com/questions/10048485/how-to-clear-remove-observable-bindings-in-knockout-js?lq=1). However, if you structure the DOM to be *only* modified from KO bindings (if/foreach/template/views-in-Durandal) on observables then everything should cleanup automatically. – user2864740 Dec 09 '13 at 22:34
  • Thanks, i could not make cleanNode work. Both the html and the viewmodel was dynamically generated by jquery-ui. So, I tried cleaning the node before binding, but it was throwing error if there was not a binding already. – faisal Dec 09 '13 at 22:53

2 Answers2

0

You shouldn't need to remove the span from the DOM. Simply modify your KO span to include a 'visible' binding for an observable boolean. Then, when you want to "hide" your span, simply set the boolean to false.

<span data-bind="text: dialog_body, visible: show_span"></span>

Then in your KO code, make your boolean observable:

var viewModel = { 
    show_span: ko.observable(true);
}

And when you are ready to hide the span:

viewModel.show_span(false);
Bo TX
  • 424
  • 2
  • 7
  • My problem was more complex than the example I gave. I am trying to bind knockout templates on jquery-ui dialogs. – faisal Dec 09 '13 at 22:55
0

jQuery has nothing to do with Knockout. It can remove nodes - but this won't clean up any bound KO observables. In the given case this will mean there is a slight memory leak as KO maintains data via an internal collection (see ko.utils.domData) after the node is simply removed with jQuery.

Two traditional methods used in KO to cleanup after itself are cleanNode and removeNode (however neither will remove bound events!) which should be used as needed .. using cleanNode (on a node bound via KO) is the minimum required to clean up data.


However, I don't think that this is a suitable place to manually clean up KO! The standard bindings will already handle cleanup, if used correctly.

Instead, write the code like the following. (See Creating custom bindings that control descendant bindings for withProperties; you'll also have to make it virtual-element compatible to use it as below.)

<div id='my_div'>
  <!--ko 'if': someObservable-->
    <!--ko withProperties: { data: someObservable() }-->
      <span data-bind="text: data.dialog_body"></span> 
    <!--/ko-->
  <!--/ko-->
</div>

Then simply set the observable to something to create the node ..

someObservable(myVm)

.. or undefined to clear it ..

someObservable(undefined)

After all, one generally won't really $('#my_div').remove() but will rather $('#my_div').dialog('close'). Actually removing the node will work just as well, as long as the same element is added back later for the new dialog.

The someObservable value could come from the "root" view model - I recommend having a root view model! - or it could come from a window property, for those feeling hackish:

window.someObservable = ko.observable()
user2864740
  • 60,010
  • 15
  • 145
  • 220
  • Having a global observable is not an option for me, as I am working in a very big project and global variable can screw up things. However, If I can get the current binding from an id, then I can change the observable on that binding. Perhaps, `ko.dataFor` or `ko.contextFor` will help. – faisal Dec 09 '13 at 23:20
  • @faisal It sounds like the big project is in need of some love then! And I would *still* recommend the above approach - but making the observable part of the containing model. Have you looked at using [Durandal](http://durandaljs.com/)? It makes it easy to apply models to different "views". (And while it supports SPA, it need not be used as an SPA.) – user2864740 Dec 09 '13 at 23:21
  • Ok, i will take a look into Durandal. Thanks. I will experiment with it and let you know. – faisal Dec 09 '13 at 23:26
  • @faisal Using `cleanNode` will work fine, however, just make sure to only use it on bound nodes. You can check using `ko.contextFor` (it should return undefined for non-bound nodes) .. or just try/catch the exception if it's used on a non-bound node. Make sure to *remove the DOM events* separately. – user2864740 Dec 09 '13 at 23:28
  • I saw your edit. my_div is not originally part of the page, but later added by jquery-ui dialog, while adding, its contents was loaded from an external knockout template and then binded. – faisal Dec 09 '13 at 23:29
  • Cool, I will try out all of your suggestions, if I make any of them work for my project, I will accept the answer. – faisal Dec 09 '13 at 23:32