41

I'm looking for unbind functionality in knockout. Unfortunately googling and looking through questions asked here didn't give me any useful information on the topic.

I will provide an example to illustrate what kind of functionality is required.

Lets say i have a form with several inputs. Also i have a view model binded to this form. For some reason as a reaction on user action i need to unbind my view model from the form, i.e. since the action is done i want all my observables to stop reacting on changes of corresponding values and vise versa - any changes done to observables shouldn't affect values of inputs.

What is the best way to achieve this?

ILya
  • 2,670
  • 4
  • 27
  • 40

3 Answers3

50

You can use ko.cleanNode to remove the bindings. You can apply this to specific DOM elements or higher level DOM containers (eg. the entire form).

See http://jsfiddle.net/KRyXR/157/ for an example.

Mark Robinson
  • 13,128
  • 13
  • 63
  • 81
  • 2
    next time write getElementById and not $("#theid")[0] its still better to use JavaScript and not jQuery for everything – guy schaller Mar 06 '13 at 15:57
  • 18
    For projects where I'm using jquery, I'm generally happy to give up 1.5ms to avoid typing an extra 15 characters. I think I'll stick with jquery selectors when I have the opportunity. – uɥƃnɐʌuop Mar 14 '13 at 23:21
  • I'd be suprised if it was even over 1ms. – Jeffrey Kevin Pry Dec 10 '13 at 15:40
  • "NetworkError: 404 Not Found - .../knockout-latest.debug.js". Fixed demo here: http://jsfiddle.net/KRyXR/156/ – Michal B. Mar 11 '14 at 08:40
  • 2
    Note that `cleanNode()` does (did? as of 2.2.1, at least) wipe that node of its event handlers, etc. Bad news for me when I had a ko-bound bootstrap modal, for instance. More here: https://github.com/knockout/knockout/issues/1130 – ruffin Jun 24 '14 at 21:29
16

@Mark Robinson answer is correct.

Nevertheless, using Mark answer I did the following, which you may find useful.

  // get the DOM element
  var element = $('div.searchRestults')[0];
  //call clean node, kind of unbind
  ko.cleanNode(element);
  //apply the binding again
  ko.applyBindings(searchResultViewModel, element);
aamir sajjad
  • 3,019
  • 1
  • 27
  • 26
  • I had to use this after manually disabling/enabling form elements in order to restore the automatic-ness of knockout's `enable` bindings. – casey Jun 14 '14 at 00:55
1

<html>
    <head>
        <script type="text/javascript" src="jquery-1.11.3.js"></script>
        <script type="text/javascript" src="knockout-2.2.1.js"></script>
        <script type="text/javascript" src="knockout-2.2.1.debug.js"></script>
        <script type="text/javascript" src="clickHandler.js"></script>
    </head>
    <body>
        <div class="modelBody">
            <div class = 'modelData'>
                <span class="nameField" data-bind="text: name"></span>
                <span class="idField" data-bind="text: id"></span>
                <span class="lengthField" data-bind="text: length"></span>
            </div>
            <button type='button' class="modelData1" data-bind="click:showModelData.bind($data, 'model1')">show Model Data1</button>
            <button type='button' class="modelData2" data-bind="click:showModelData.bind($data, 'model2')">show Model Data2</button>
            <button type='button' class="modelData3" data-bind="click:showModelData.bind($data, 'model3')">show Model Data3</button>
        </div>
    </body>
</html>

@Mark Robinson gave perfect solution, I've similar problem with single dom element and updating different view models on this single dom element.

Each view model has a click event, when click happened everytime click method of each view model is getting called which resulted in unnecessary code blocks execution during click event.

I followed @Mark Robinson approach to clean the Node before apply my actual bindings, it really worked well. Thanks Robin. My sample code goes like this.

function viewModel(name, id, length){
  var self = this;
  self.name = name;
  self.id = id;
  self.length = length;
 }
 viewModel.prototype = {
  showModelData: function(data){
  console.log('selected model is ' + data);
  if(data=='model1'){
   ko.cleanNode(button1[0]);
   ko.applyBindings(viewModel1, button1[0]);
   console.log(viewModel1);
  }
  else if(data=='model2'){
  ko.cleanNode(button1[0]);
   ko.applyBindings(viewModel3, button1[0]);
   console.log(viewModel2);
  }
  else if(data=='model3'){
  ko.cleanNode(button1[0]);
   ko.applyBindings(viewModel3, button1[0]);
   console.log(viewModel3);
  }
 } 
 }
 $(document).ready(function(){
  button1 = $(".modelBody");
  viewModel1 = new viewModel('TextField', '111', 32);
  viewModel2 = new viewModel('FloatField', '222', 64);
  viewModel3 = new viewModel('LongIntField', '333', 108);
  ko.applyBindings(viewModel1, button1[0]);
 });
 
Raju Putchala
  • 96
  • 1
  • 7