Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the preferred way to store state between init and update for custom knockout binding?

Tags:

knockout.js

Currently I am storing the state using jQuery data for the dom element.

ko.bindingHandlers.customValue = {      init: function init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {         var state = { isEditing: false };                 $(element).focus(function focus() {             state.isEditing = true;         }).blur(function blur() {             state.isEditing = false;                     }).data("customBinding", state);      },      update: function update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {         // ignore if updating         if (!$(element).data("customBinding").isEditing) {             // handle update if they are not updating                                         }     }  };​ 

Is there a better place to store state per binding that does not require the dom? Can the bindingContext be used to store state for the each instance of the binding?

like image 574
Drew Turner Avatar asked Apr 15 '12 21:04

Drew Turner


People also ask

What is two-way binding in KnockoutJS?

KO is able to create a two-way binding if you use value to link a form element to an Observable property, so that the changes between them are exchanged among them. If you refer a simple property on ViewModel, KO will set the form element's initial state to property value.

What does Ko unwrap do?

unwrap method is used to read it), the current viewModel and bindingContext. Whenever the passed value changes the binding will print updated information to console. This binding cannot be used with virtual elements (in html comments), only on real elements, since ko.

What is knockout library?

Knockout is a JavaScript library that helps you to create rich, responsive display and editor user interfaces with a clean underlying data model.


1 Answers

The bindingContext is a possibility, but only for passing data from init to update the first time that the binding is triggered. The next time that update fires it would no longer be there.

There are really two choices for where to store this type of state:

1- On the element, as you stated. You can use jQuery's $.data or KO includes APIs for doing this as well ko.utils.domData.get(element, key) and ko.utils.domData.set(element, key, value).

2- Put this type of information in your view model, if appropriate. A flag to indicate isEditing is not necessarily out of place in a view model. I personally like to put this type of "meta-data" as sub-observables off of an observable like:

var name = ko.observable("Bob"); name.isEditing = ko.observable(false); 

You would be able to bind against name and name.isEditing.

This has some advantages:

  • keeps the view model fairly clean, as you are not introducing new top-level properties
  • keeps the sub-observable tied to its parent observable (no need for nameIsEditing, etc.)
  • when turned into JSON with something like ko.toJSON the isEditing sub-observable will simply be dropped when its parent is unwrapped. So, you won't be sending unnecessary values back to the server.
  • in this case, it can also have the advantage of being available for other calculations in your view model or to bind against multiple elements in your UI.
like image 179
RP Niemeyer Avatar answered Sep 28 '22 04:09

RP Niemeyer