Knock Me Out

Thoughts, ideas, and discussion about Knockout.js

Knockout.js Bindings for Kendo UI

| Comments

Recently, I spent much of my late hour programming time working on a project to create a set of Knockout.js bindings for the Kendo UI web widgets. After being involved in several discussions about how Kendo UI could integrate with Knockout, I decided to jump in and try to provide a place where this integration could officially exist and grow. As a result, there is now a project on Github for these bindings.

+

Kendo UI – a great framework

If you are not familiar with Kendo UI, then take a look at the demos and documentation. Also, take note of the licensing requirements. I am not affiliated with Telerik in any way, but am quite impressed with the framework. In my experience, it is an excellent product with good people working on it.

When developing these bindings, the first challenge that I found was how to simultaneously write, test, and document 19 custom bindings. After writing a couple of the bindings “by hand”, I decided to take a different route and create a factory that could generate the bindings. The idea is that you pass in some configuration and it can produce a proper binding for you. This would allow for the sharing of common code, easier maintenance/enhancements, and the ability to generate some standard tests for each widget from the configuration.

A pattern for 3rd party widget bindings

To create the bindings, I followed a pattern that I like to use for custom bindings against 3rd party widget that involves these steps:

  • Prepare the options needed to initialize the widget
  • Subscribe to any events triggered by the widget that require an update to the model
  • Initialize the widget
  • Register to destroy the widget when KO removes this element *Use either the update function or individual computed observables created in the init function to update the widget based on changes to the model.

This covers creating the widget and syncing changes between the model and the widget. However, for these bindings I wanted to support a couple of additional features:

  • The ability to define global default options for a widget. The binding will merge any options passed in the data-bind attribute with these global options. This helps to keep the mark up clean by not forcing you to include all of the configuration in the binding string.
  • The ability to access the actual widget from the view model. If you pass a “widget” option to the binding, then it will fill that observable with a reference to the actual widget. This allows you to call methods of the widget from within view model methods, if necessary.

Next Steps

With these particular bindings, I hope to look at bringing tighter integration with templating and data sources. Many of the widgets (Grid, ListView) need this type of support to fit naturally in a Knockout application. I also hope to see what kind of feedback comes from real-world usage to decide the next steps.

Additionally, if there is enough demand, it would be interesting to apply this factory concept to other widgets like jQuery UI, YUI , and/or the Bootstrap plugins.

One final note: Kendo UI recently released their own native MVVM implementation. It has a Knockout flavor to some of the syntax and integrates well with the widgets. It is definitely an option to consider, if you are “all in” on Kendo UI.

Knockout-Kendo.js project link

Revisiting Dragging, Dropping, and Sorting observableArrays

| Comments

Earlier I explored a set of Knockout.js bindings that would allow dragging and dropping items in an observableArray. These bindings could either be used to sort items in a single array or to move items between arrays. With Knockout 2.0, I wanted to take a fresh look at how this can be accomplished. The resulting project is here.

Areas for improvement

The original syntax that I was using for binding to a single array looked like:

1
2
3
4
<div class="container"
  data-bind="template: {name: 'taskTmpl', foreach: tasks},
    sortableList: tasks">
</div>

The syntax for binding multiple arrays, required additional data to be passed to the chlidren. The parent looked like:

1
2
3
4
5
6
<div class="container"
  data-bind="template: {name: 'taskTmpl',
    foreach: highPriorityTasks,
    templateOptions: { parentList: highPriorityTasks} },
    sortableList: highPriorityTasks">
</div>

The child elements required some meta-data to be attached via a binding:

1
<div data-bind="sortableItem: { item: $data, parentList: $item.parentList }" >

This syntax is far too verbose and forces us to use too many bindings to make this work. My goal is to use a single binding that will work for both a single array and moving items between arrays. Ultimately, I wanted to simplify it down to something like this:

1
2
3
<ul data-bind="sortable: tasks">
  <li data-bind="text: name"></li>
</ul>

or if using named templates like:

1
<ul data-bind="sortable: { tmpl: 'taskTmpl', list: tasks }"></ul>

What does our single binding need to accomplish?

  1. We are not specifying the template or foreach binding, so our binding will have to wrap this functionality by calling the template binding with the appropriate options.
  2. We are not specifying any bindings on the children, so we need to find a way to attach meta-data to the children, so we can retrieve the data and original parent from a dropped element. Since we are calling the template binding, we can use its afterRender option to add the meta-data.
  3. The element require a certain class to be hooked up as a target. We should handle adding this class in the binding rather than requiring the developer to add it (or forget to add it).
  4. We still need to initialize the container by calling jQuery UI’s .sortable and specify how to handle an item being dropped.
  5. We should also call the sortable widgets destroy method when Knockout removes the element (perhaps by the template binding).

How about some extra features?

With these features in place, we can clean up the syntax required on the element and still accomplish the same functionality as before. However, there are a few additional enhancements that I felt would be useful in the binding:

  1. You can configure the class that is used on the element to enable it as a drop target (the connectWith class).
  2. You can specify a function, observable, or static value to determine whether the element is a target for dropping. This will toggle the class based on the supplied value and react if it changes.
  3. The binding accepts a beforeMove function that allows you to perform an action prior to the item being moved from its original location to its new destination. This function can also cancel the move.
  4. The binding also accepts an afterMove function to perform an action after the item has been moved to its new index it the destination array.

Each of these options can be specified in the binding like:

1
<ul data-bind="sortable: {data: items, afterMove: saveData, allowDrop: isBucketFull}"></ul>

Additionally, each feature can be configured with a global default. This keeps the markup/bindings clean when the options will apply to all or most of the bindings. This would look like:

1
2
3
ko.bindingHandlers.sortable.connectClass = "myContainer";
ko.bindingHandlers.sortable.allowDrop = viewModel.isBucketFull;
ko.bindingHandlers.sortable.afterMove = viewModel.saveData;

Samples

Single Todo list:

Link to sample on jsFiddle.net

Connected Todo lists:

Link to sample on jsFiddle.net

Seating chart:

Link to sample on jsFiddle.net

knockout-sortable Project

The binding is up on github here: https://github.com/rniemeyer/knockout-sortable. I am definitely looking for feedback and suggestions for additional functionality, as well as working to improve the docs, specs, examples.

Knockout 2.0 Is Out!

| Comments

KnockoutJS 2.0 is available now! This version was formally known as 1.3 and has been in the works for quite a while. It includes substantial changes that are mainly focused on allowing developers to write cleaner and simpler code while providing additional extensibility points to that allow better control of how Knockout is used. has been thoroughly updated for this release with changes to docs, examples, and tutorials along with some additional advanced topics.

A few links:

KnockoutJS 2.0 is an exciting release. The native templating and control-flow bindings allow an easier and streamlined way to change scope and repeat content. It is no longer required to reference an external engine like the jQuery Templates plugin to do templating in Knockout. Even jQuery is not a strict dependency. The additional extensibility points allows developers to explore using Knockout in different ways, such as applying bindings in code rather than declaratively.

I would expect a 2.0.x release in the near future that will include some further performance tweaks that are being explored, but overall 2.0 feels very solid. Go try it now and please leave feedback here or here.

Knockout 1.3 Release Candidate + a New Feature

| Comments

Update: Knockout 1.3 was eventually renamed to version 2.0

Just a quick note: the Knockout.js 1.3 release candidate is now available for testing. Barring any last-minute fixes, this should be the final version. Files are available from: https://github.com/SteveSanderson/knockout/tree/master/build/output.

Some links to 1.3 information:

Currently, I am working with Steve on documentation updates to <Knockoutjs.com> before a final release. Hopefully, it will be ready soon!

Controlling when to receive subscription notifications

There were was one feature added recently, which hasn’t been covered, that I wanted to briefly highlight. Knockout 1.3 now allows you to decide when you want to be notified before or after a value has changed when creating a manual subscription. The default behavior, as before, is that the subscription runs after the value has changed and passes the new value as the first argument.

When creating a manual subscription, you can now opt to have your code run before the value has changed and receive the previous value as the first parameter. To be notified before the value changes, the subscribe API now accepts a third parameter to specify an event name.

1
2
3
viewModel.price.subscribe(function(value) {
    this.history.push({ value: value, time: new Date() });
}, viewModel, "beforeChange");

If the event name is not passed, then it will default to change, which is consistent with the current behavior of manual subscriptions.

This can be useful to take action before a value has changed or to track changes to values. Previously, you could have accomplished this with a writeable dependentObservable in front of the actual observable, but this allows a more direct way to accomplish this type of action.

While change and beforeChange are the only events that Knockout uses itself, we are able to subscribe to custom events. We would couple this with the use of the notifySubscribers method on an observable to trigger messages for those events. This could be useful in certain scenarios where your application wants to delegate responsibilities to other components.

1
2
3
4
5
6
7
8
9
viewModel.price.subscribe(function(newValue) {
    if (!newValue) {
        this.price.notifySubscribers(null, "valueRemoved");
    }
}, viewModel);

viewModel.price.subscribe(function() {
    //react to the value being removed
}, viewModel, "valueRemoved");

As shown above, we can create an overall subscription to an observable that looks at its state and decides when to notify subscribers of any appropriate events. These could be chained together and allow us to create components that expose specific events to subscribers. Seems like a potentially useful feature to consider when creating a reusable library with Knockout.

KO 1.3 Preview Part 3: Template Sources

| Comments

Update: Knockout 1.3 was eventually renamed to version 2.0

Knockout 1.3 contains a number of enhancements that allow developers to extend the default capabilities of the library. Besides custom binding providers, you can now also create objects that define how to get and set a template’s contents based on the template name. These objects are called templateSources.

Knockout’s default templateSources

Knockout includes two templateSources that are used by default. The first templateSource understands how to retrieve a template from a DOM element using the template name as the id of the element. Typically, these are the templates that live in script tags. The other deals with anonymous templates, where the children of the element are used as the template. Anonymous templates are used when a name is not provided to the template binding and is most commonly used with the new control-flow bindings.

What does a templateSource look like?

A templateSource needs to provide a text and a data function. Similar to an observable, the text function when given no arguments should return the text of the template. When passed a single parameter, the function should write that value to wherever the template is being stored.

The data function is used to associate additional metadata related to the template and should accept key and value parameters. If only passed the key parameter, it should return the value. If passed both arguments, then it should use the key to write the value to an appropriate location. This meta-data is currently used for things like indicating that a template has been rewritten and to set/retrieve a precompiled version of a jQuery template.

A quick note about rewriting templates

When using a third-party engine, Knockout needs to take special care to ensure that the proper scope is available when applying bindings. You might want to use variables that are exposed by the template engine in your data-bind attributes or you may be looping over arrays using the template engine’s syntax and adding bindings on elements inside the loop. These are cases where Knockout can rewrite the template to allow bindings to execute under the proper context, as long as the template engine knows how to create a block to execute arbitrary JavaScript. Note that the new native template engine does not require this rewriting.

Writing a quick custom templateSource

Suppose that we want to keep our templates in strings. Maybe we want to load them from the server or even generate them on-the-fly. For starters, we can maintain an object that stores our template text by key like:

1
2
3
4
templates: {
    viewTemplate: "<li data-bind='text: name'></li>",
    editTemplate: "<li><input data-bind='value: name' /></li>"
}

To create our templateSource, let’s first write a constructor function that takes in the name of our template and the object that holds our templates.

1
2
3
4
ko.templateSources.stringTemplate = function(template, templates) {
    this.templateName = template;
    this.templates = templates;
};

Next our templateSource needs to provide a text method. When passed no parameters, we need to return our template from the template object. When passed a value (in the case of a rewritten template), we need to set the value on the template object. This method can be as simple as:

1
2
3
4
5
6
text: function(value) {
     if (arguments.length === 0) {
        return this.templates[this.templateName];
     }
     this.templates[this.templateName] = value;
}

Now we need a data method for storing any meta-data about the template. We could have our template object store text and data properties for each key, but to keep the template definitions simple, I am going to tuck the meta-data into a _data key on the template object.

1
2
3
4
5
6
7
8
9
10
data: function(key, value) {
    this.templates._data = this.templates._data || {};
    this.templates._data[this.templateName] = this.templates._data[this.templateName] || {};

    if (arguments.length === 1) {
        return this.templates._data[this.templateName][key];
    }

    this.templates._data[this.templateName][key] = value;
}

This method just ensures that the proper objects have been created and then does a get or set using the key.

There is one last step that we need to perform to take advantage of our new type of templateSource. We need to override the makeTemplateSource function of a template engine. To be flexible, we can create a function that takes in an existing template engine and the location of our string templates.

1
2
3
4
5
6
function createStringTemplateEngine(templateEngine, templates) {
    templateEngine.makeTemplateSource = function(template) {
        return new ko.templateSources.stringTemplate(template, templates);
    }
    return templateEngine;
}

Finally, we need to tell Knockout to use an appropriate template engine.

1
ko.setTemplateEngine(createStringTemplateEngine(new ko.nativeTemplateEngine(), viewModel.templates));

Here is a sample using this technique:

Link to sample on jsFiddle.net

You could even extend this concept to create a template source that loads its contents from an external source. Here is a sample that uses an observable to store the template contents, which allows the use of a loading template while the real template is being retrieved:

Link to sample on jsFiddle.net

Knockout 1.3 definitely has some great new extensibility features. While the default templateSources should be sufficient for most applications, it is nice to know that there is some flexibility built in to deal with templates in other ways.