Version 3.0.0 beta

@mbest mbest released this Jul 8, 2013 · 511 commits to master since this release

  1. Independent bindings: When an element has more than one binding, such as visible: showPlaylist, template: 'playlistTmpl', each binding is updated in a separate computed observable, and observables accessed by one binding won't affect any others. To receive all the benefits of independent bindings, you should note the following interface changes: (The old interfaces are still supported for backwards compatibility.)

    • Within binding handlers, access sibling bindings by calling the get method of the allBindings parameter. To check for the existence of a sibling binding, use the has method. Getting the value of a sibling binding adds a dependency on any observables accessed in the binding's value expression.
    • ko.applyBindingsToNode is superseded by ko.applyBindingAccessorsToNode. The second parameter takes an object with pairs of bindings and value-accessors (functions that return the binding value). It can also take a function that returns such an object. (This interface isn't currently documented on the website.)
    • A binding provider should implement a getBindingAccessors function instead of (or in addition to) getBindings. Similarly to the above, it should return an object with bindings and value-accessors for any nodes that have bindings. (The binding provider interface also isn't documented on the website.)
  2. Ordered bindings: When an element has more than one binding, and when the order of updating those bindings is important, such as value: selectedValue, options: choices, Knockout will bind them in the right order. This is handled automatically for built-in bindings, and custom bindings can take advantage of this through a new interface. A binding handler can have an after property with an array of other bindings that it should come after. For example, the value handler has after: ['options', 'foreach'].

  3. Preprocessing bindings: Binding handlers can define a preprocess function that is called with the code of the binding value before it is evaluated. This can be used to modify the value or add extra bindings based on the value. Suppose you have a binding that expects a string, but you want to allow the user to provide an unquoted string. You could define a preprocess function that adds quotes to unquoted values:

    preprocess: function(value) {
        if (value[0] !== "'" && value[0] !== '"')
            return '"' + value + '"';
            return value;
  4. Preprocessing nodes: The binding provider can define a preprocessNode function that is called with each node in the document before it is processed for bindings. This function can modify the node or replace it with new nodes. This could be used to make syntax like Name: {{ firstName }} work by detecting {{ expr }} expressions in text nodes and inserting <!-- ko text: expr --><!-- /ko --> before binding are applied to that node.

  5. Dynamic binding handlers: Normally, binding handlers are defined before bindings are applied by adding handler objects to ko.bindingHandlers. But you can also define handlers dynamically by overriding the ko.getBindingHandler function. This function is given a binding string and returns the handler for that binding (or undefined if none exists). Here's an example that allows you use any binding starting with data- to set data attributes:

    var originalGetHandler = ko.getBindingHandler;
    ko.getBindingHandler = function(bindingKey) {
        var handler = originalGetHandler(bindingKey);
        if (!handler && bindingKey.match(/^data-/)) {
            handler = ko.bindingHandlers[bindingKey] = {
                update: function(element, valueAccessor) {
                    element.setAttribute(bindingKey, ko.unwrap(valueAccessor()));
        return handler;
  6. checkedValue binding: Normally, the checked binding will use the input's value property, which is limited to string values, when updating its value. But if you also provide a checkedValue binding, its value will be used instead; this provides a way to use a value of any type with the checked binding.

  7. Observable view models: This is still a bit experimental. The idea is that you can have the view model be dynamic without having to use templates and re-render the whole DOM. Instead, changing the view model will update each of the individual bindings. More detail later...

  8. options binding generates change event: When the options change, the options binding tries to maintain the list selection so that the value of the selection stays the same. But if the selection changes because the selected value was removed, the options binding will generate a change event for the element. Other bindings that listen for change events, such as value and selectedOptions, will then be updated.