SoFunction
Updated on 2025-04-10

Knockout custom binding creation method

Overview

In addition to the built-in binding types of KOs listed in the previous article (such as value, text, etc.), you can also create custom bindings.

Register your binding handler

 = {
  init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    // This will be called when the binding is first applied to an element
    // Set up any initial state, event handlers, etc. here
  },
  update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    // This will be called once when the binding is first applied to an element,
    // and again whenever any observables/computeds that are accessed change
    // Update the DOM element based on the supplied values here.
  }
}; 

Next you can use custom bindings on any dom element:

<div data-bind="yourBindingName: someValue"> </div> 

Note: You don't have to provide both init and update callbacks in your handler, you can provide any one.

update callback

As the name implies, when your monitoring attribute observable is updated, ko will automatically call your update callback.

It has the following parameters:

element: Use this bound dom element;

valueAccessor : The currently bound model attribute value can be obtained by calling valueAccessor(), and the call (valueAccessor()) can more conveniently obtain the observable value and normal value;

allBindings: binds to all attribute values ​​of the model on this dom element, for example, calling ('name') returns the bound name attribute value (returned undefined if it does not exist), or calling ('name') to determine whether the name is bound to the current dom;

viewModel : Deprecated in Knockout.3x, you can use bindingContext.$data or bindingContext.$rawData to get the current viewModel;

bindingContext : binds the context, and can call bindingContext.$data, bindingContext.$parent, bindingContext.$parents, etc. to obtain data;

Next, let’s take an example. You may want to use visible bindings to control the visibility of elements and add animation effects. At this time, you can create your custom bindings:

 = {
  update: function(element, valueAccessor, allBindings) {
    // First get the latest data that we're bound to
    var value = valueAccessor();
    // Next, whether or not the supplied model property is observable, get its current value
    var valueUnwrapped = (value);
    // Grab some more data from another binding property
    var duration = ('slideDuration') || 400; // 400ms is default duration unless otherwise specified
    // Now manipulate the DOM element
    if (valueUnwrapped == true)
      $(element).slideDown(duration); // Make the element visible
    else
      $(element).slideUp(duration);  // Make the element invisible
  }
}; 

Then you can use this custom binding like this:

<div data-bind="slideVisible: giftWrap, slideDuration:600">You have selected the option</div>
<label><input type="checkbox" data-bind="checked: giftWrap" /> Gift wrap</label>
<script type="text/javascript">
  var viewModel = {
    giftWrap: (true)
  };
  (viewModel);
</script> 

init callback

ko will call your init function for each of the bound dom elements, which has two main uses:

(1) Set the initialization state for the dom element;

(2) Register some event handlers, for example: when the user clicks or modifies the dom element, you can change the status of the monitoring attribute;

ko will use the exact same set of parameters as the update callback.

Continuing with the previous example, you may want slideVisible to set the visibility state of the element when the page is displayed for the first time (no animation effect), and the animation effect is executed when it changes later. You can do it in the following way:

 = {
  init: function(element, valueAccessor) {
    var value = (valueAccessor()); // Get the current value of the current property we're bound to
    $(element).toggle(value); // jQuery will hide/show the element depending on whether "value" or true or false
  },
  update: function(element, valueAccessor, allBindings) {
    // Leave as before
  }
}; 

GiftWrap is initialized and defined as false ((false)). The associated DIV will be hidden during initialization, and then the DIV will be displayed when the user clicks checkbox.

You now know how to use the update callback. When the observable value changes, you can update the dom element. We can now use another method, for example, when the user has a certain action operation, it can also cause your observable value to be updated, for example:

 = {
  init: function(element, valueAccessor) {
    $(element).focus(function() {
      var value = valueAccessor();
      value(true);
    });
    $(element).blur(function() {
      var value = valueAccessor();
      value(false);
    });
  },
  update: function(element, valueAccessor) {
    var value = valueAccessor();
    if ((value))
      ();
    else
      ();
  }
}; 

Now you can read and write your observable value through the "focusedness" binding of the element.

<p>Name: <input data-bind="hasFocus: editingName" /></p>
<!-- Showing that we can both read and write the focus state -->
<div data-bind="visible: editingName">You're editing the name</div>
<button data-bind="enable: !editingName(), click:function() { editingName(true) }">Edit name</button>
<script type="text/javascript">
  var viewModel = {
    editingName: ()
  };
  (viewModel);
</script>

The above content is the Knockout custom binding creation method shared by the editor. I hope you like it.