Unbind view model from view in knockout
Asked Answered
S

3

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?

Snashall answered 14/6, 2012 at 11:29 Comment(0)
B
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.

Buttonwood answered 14/6, 2012 at 12:52 Comment(5)
next time write getElementById and not $("#theid")[0] its still better to use JavaScript and not jQuery for everythingLashanda
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.Agog
I'd be suprised if it was even over 1ms.Fumed
"NetworkError: 404 Not Found - .../knockout-latest.debug.js". Fixed demo here: jsfiddle.net/KRyXR/156Paralyze
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: github.com/knockout/knockout/issues/1130Yelenayelich
S
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);
Surra answered 11/2, 2013 at 9:42 Comment(1)
I had to use this after manually disabling/enabling form elements in order to restore the automatic-ness of knockout's enable bindings.Anecdotic
L
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]);
	});
	
Lissa answered 20/10, 2016 at 6:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.