spacer
 
 

Knockout 2.0.0 released

Posted on December 21, 2011

Here it is at last! Knockout 2.0.0 contains a huge set of improvements since the 1.2.x line. If you’re using KO already, see below for some of the highlights.

New to all this? Now’s a great time to check it out. Knockout is an MVVM library for JavaScript – it makes rich dynamic web UIs easier and cleaner to build. The best place to start learning is with the interactive tutorials.

What just happened?

  • The finished 2.0.0 build is now on GitHub
  • All of the documentation and live examples are updated to reflect the new version
  • All of the interactive tutorials are updated too.

Credits go to the many community members who contributed pull requests, bug reports, new documentation, and support during this process. These people include aaronpowell, amonat, antis, aredridel, artiomchi, barkmadley, b-dur, bmac, cburgdorf, develop-me, DomenicDenicola, doodlemoonch, dre2901, drewlesueur, ducka, gigi81, GLuKKi, hunterloftis, ifandelse, joeldart, kmalakoff, lcbarcellos, mbest, mtscout6, neonstalwart, owenssam, Quaternion, rniemeyer, RoyJacobs, schinckel, seanami, SimonBartlett, studgeek, tehsenaus, and tiberiuana – and that’s just those who made recent pull requests (apologies for not tracking everyone who contributed other things). rniemeyer wrote a lot of documentation too.

Why is it called 2.0.0? Why not 1.3.0?

For a long time, we were planning this next version to be called 1.3.0. However,

  • Quite a few community members are keen on adopting SemVer-style versioning. 2.0.0 is a good place to start (expermentally) with that versioning convention.
  • It’s such a big set of core changes that if this doesn’t count as 2.0, I guess nothing ever would…

New features

I’m mostly going to copy and paste the “what’s new” list from my earlier blog post about Knockout 1.3 beta, with a few further updates. Besides these things, there are all the usual bugfixes and performance improvements that you’d expect.

1. Control flow bindings

Previously, if you wanted to display a repeating sequence of UI elements (“foreach”), or have a section of the DOM exist only if some viewmodel condition was true (“if”), you’d need to create an entire template to define that. A bit cumbersome for something so simple and commonplace! Now you can use the new control flow bindings – if, ifnot, with, and foreach – to achieve basic, declarative control flow without the need for a template. This can make your code a lot more elegant and to-the-point.

Here’s an example of using “foreach” and “if”:

Tip: Switch to the “result” tab to see the output

The "with" binding changes the binding context to whatever object you specify. This makes it easy to compose many independent view models together – you have a host model that contains references to its children, and then use "with" to bind different sections of the page to different child models. Example:

Of course, the "if", "ifnot", "foreach", and "with" bindings can all be combined and nested arbitrarily.

2. Containerless control flow

What if you want to set up template-less control flow (as in the above example), but without having to use extra container elements just to hold the "foreach", "if", etc., bindings? In that case, you can use the new comment-based control flow syntax like this:

The comment-based control flow syntax works with the "if", "ifnot", "foreach", "with", and "template" bindings. In a large number of cases, this means you can skip string-based templates and use the binding-based control flows instead, which can run much faster depending on what exactly you’re doing.

3. Access to parent binding contexts

Whether you’re using regular nested templates, or nesting the new control flow blocks, sometimes you want to reference properties that exist at the upper levels of binding. There are four new pseudo-variables that you can use in any binding (inside or outside traditional templates):

  • $data – returns the current item
  • $parent – returns the item from the parent binding context
  • $parents – an array containing all the parent binding contexts. $parents[0] == $parent, then $parents[1] is the level above that, and so on.
  • $root – returns the item at the top level of binding (usually your primary view model)

Example:

4. Cleaner event handling

In most cases, data-bind attributes can be kept clean and elegant. But one rough spot in the past has been event handlers, because to pass parameters, you were generally guided to use function literals. For example:

<button data-bind="click: function() { viewModel.items.remove(this) }">Click me</button>

Many of you rightly pointed out that this is pretty ugly. It’s much nicer if bindings can be kept minimal and declarative! To fix this, KO 2.0 offers two alternative event handling syntaxes, both of which are better.

Firstly, event handlers now receive the current model value as their first parameter. So, you can implement “remove-from-list” as follows, with no inline function literals:

The other option is to use jQuery event delegation to catch events and invoke functions on your viewmodel. This is made possible by the ko.dataFor and ko.contextFor helpers, which tell you which part of your viewmodel a given event relates to. Here’s the preceding example, but now using event delegation:

5. Binding providers (and hence external bindings)

Most KO developers find the default data-bind attributes provide a very convenient, easy-to-maintain way of declaratively associating viewmodels with views. But if you would prefer to store your binding configuration elsewhere, the new binding providers API is an extensiblity point that allows alternative configuration mechanisms to be plugged in.

For example, here’s one possible alternative way that you could configure bindings. Notice the absence of data-bind attributes – I’m using a binding provider to set up the binding configuration in JavaScript:

To be clear, binding providers are a general extensibility mechanism, not any specific configuration format. The above example is just one possible way it can be used to define bindings in JavaScript. I’m looking forward to seeing suggestions from the community about how this extensibility can be used, and for what the most elegant and convenient way of defining bindings might be. I know some of you have already suggested externalising bindings (e.g., Brandon Satrom’s knockout.unobtrusive plugin); this new API will make it easier to implement custom binding mechanisms. Bring on more plugins!

6. Throttling

Note: ko.computed is Knockout 2.0’s new name for ko.dependentObservable – it’s easier to say, type, and explain. This doesn’t affect backward compatibility, though – ko.dependentObservable still works, because it references the same function instance as ko.computed at runtime. You don’t have to change your existing code if you don’t want.

Occasionally, it’s desirable to limit how fast observables and computed observables update. For example, you might be using a ko.computed to invoke Ajax requests whenever a set of observables change. Sometimes you might want to change multiple underlying observables, but only have that ko.computed re-evaluate once, after all the changes (so that it only fires one Ajax request). Effectively, you want a kind of atomic update.

This is now pretty easy to do: you can apply an extender called "throttle" either to observables or to computed observables. For example:

// Will not notify changes faster than once per 500ms 
var myObservable = ko.observable("initial value").extend({ throttle: 500 });
 
// Will not re-evaluate *or* notify changes faster than once per 500ms 
var myComputed = ko.computed(function() { 
    // Evaluation logic goes here, usually referencing other observables 
    return 123;
}).extend({ throttle: 500 });

The way this works is that, when throttled, notifications and evaluations are done asynchronously, and don’t occur at all until they stop being triggered for the specified throttle timeout duration.

In the case of making a computed value only update once even if there are multiple synchronous changes to its dependencies, you can use a very short timeout (for example, 1ms), and then it will re-evaluate as soon as possible after any series of synchronous changes to its dependencies. Example:

Breaking changes

There are two changes that might realistically affect existing 1.2.x application code. Both are for good reasons and are important for the long-term health of the project…

  • Event handlers now receive your model object as their first parameter, and the DOM event object as the second parameter. Previously, they only received the DOM event object as the first parameter. So, if you are using the “click” or “event” bindings and are specifically catching and using the DOM event object, you’ll need to change your handler’s signature from this:

myViewModel.myEventHandler = function(evt) { /* do something with evt */ }

… to this:

myViewModel.myEventHandler = function(data, evt) { /* do something with evt */ }

This will not affect any event handlers that don’t specifically receive and process the “event” parameter. We chose to make this change because it significantly simplifies event handling in the majority of cases. Most developers have been able to upgrade to 2.0.0 beta without changing their applications at all.

  • KO 2.0.0 drops support for very old versions of jquery-tmpl. If you need to use string-based templating (and most often you won’t now that KO 2.0.0 has native control flow bindings), get jquery-tmpl 1.0.0pre. But also consider dropping the string-based templating, and switching to control flow bindings instead, as jquery-tmpl is no longer in active development.

Summary

Try the updated interactive tutorials, update your existing KO applications, have a great Christmas/vacation/newyear spacer

- 39 Comments - Posted in Javascript, Knockout

< Full-height app layouts: Navigation and History

39 Responses to Knockout 2.0.0 released

  1. spacer J. Gagnon

    Nice! I’ll use it on my next project for sure!

    Thanks !
    J

    Posted on December 21, 2011
  2. spacer Steve W

    Excellent, nice to see a release, now we can update from the RC.

    Thanks for all the hard work on this, knockout is a really nice way to write in-browser functionality.

    Posted on December 21, 2011
  3. spacer Tyler Cole

    Steven Sanderson and the entire team at KnockoutJS – I can’t believe the number of useful changes you’ve made. Every single change on this list is useful to me, and I fully intend to use it on a current project under active development! All I can say is, keep up the excellent work you guys!

    Posted on December 21, 2011
  4. spacer Marcel du Preez

    I agree with the giant laughing pear thing!

    Posted on December 21, 2011
  5. spacer SI Hayakawa

    typo: “good place to start (expermentally)” — should be “experimentally”

    Posted on December 21, 2011
  6. spacer Alagesann Palani

    Really great features, will try them all this christmas holidays. Great job.

    Posted on December 21, 2011
  7. spacer Jeremy

    Been using KO for a week, have been loving it… now I’m in major crush mode. Thanks for the update!

    Posted on December 21, 2011
  8. spacer Jamey

    In production now with two simple projects and currently building my first single page. I can’t thank you guys enough for knockout.js. !!!

    Posted on December 21, 2011
  9. spacer Ben W

    Excellent.

    Posted on December 21, 2011
  10. spacer JackNova

    great! great! great! I’m testing already and it rocks!

    Posted on December 21, 2011
  11. spacer JackNova

    what about using an apply invocation pattern over the constructor in “List and Collections” example?

    Posted on December 21, 2011
  12. spacer Harsha

    Thanks Steven. I am using this version from its beta stage.

    Computed method is new to me. I am going replace dependentObservables today.

    Posted on December 22, 2011
  13. spacer Xin SU

    Great!
    Throttling is very useful to me and I really like Containerless control flow feature spacer

    Thank you all the community members, Knockout is excellent.

    Posted on December 22, 2011
  14. spacer zbrong

    Great sanderson !
    I’m waited for a long time. thank u very much !!!

    Posted on December 22, 2011
  15. spacer Hashname

    Thank you Mr.Anderson spacer

    Posted on December 22, 2011
  16. spacer giles bradshaw

    I think your comments control flow thing is buggy

    This works (not what I wanted to do though):

    This doesn’t work:

    comes up with ” Cannot find closing comment tag to match: ko foreach: data “

    Posted on December 22, 2011
  17. spacer giles bradshaw

    ?? how do I post html??

    I think your comments control flow thing is buggy
    This works (not what I wanted to do though):

    This doesn’t work:

    <table>
    <!– ko foreach: data –>
    <tr>

    <td data-bind=”text: Name” ></td>

    </tr>
    <!– /ko –>
    </table>

    comes up with ” Cannot find closing comment tag to match: ko foreach: data “

    Posted on December 22, 2011
  18. spacer Steve

    Hi Giles – sorry about the blog eating your tags… spacer I keep meaning to migrate away from WordPress because of that sort of thing!

    About tables: most browsers will auto-insert implicit elements like <tbody> in a table, but the exact way they do it varies from one browser to the next. For consistency, and to ensure your comment tags end up in the right place, you’ll need to include the <tbody> explicitly in your markup.

    Here’s your example code working correctly: jsfiddle.net/StevenSanderson/cn8xk/

    BTW if you discover any other suspected issues, would it be possible to post them to https://github.com/SteveSanderson/knockout/issues ? That way they’ll be seen by more people, and will be tracked for a more timely resolution. Thanks!

    Posted on December 22, 2011
  19. spacer giles bradshaw

    Thanks for that Steve.

    Posted on December 22, 2011
  20. spacer John Papa

    Fantastic job Steve!

    Excellent new features, and a very manageable breaking changes set.

    Next up … containerless bindings for all built in binding types spacer

    Also, I like the change too for dependentObservable to computed.

    Posted on December 22, 2011
  21. spacer Stefan

    Great! Thanks for all the effort!

    Posted on December 22, 2011
  22. spacer Vin

    This is awesome, Thanks Steve and all other ko community who worked towards this.

    Can’t wait to upgrade my projects with ko 2.0

    Posted on December 22, 2011
  23. spacer dariob

    the wait is over! Thank you so much!

    Posted on December 23, 2011
  24. spacer Philippe Monnet

    Great job to the whole KnockoutJS team!
    My two favorite new features are dynamic templates and throttling.

    Posted on December 23, 2011
  25. spacer Marius Schulz

    Cool! That’s a nice Christmas present spacer . I especially like the new Control Flow Bindings and the Cleaner Event Handling.

    Please keep up the great work!

    Posted on December 23, 2011
  26. spacer zbrong

    Hi steve:
    Thank u to release the new version of KO, I like it very much!
    As the ‘jsRender’ and ‘jsViews’ will be the offical template of jQuery, will you consider to support that templates ? can we use those templates with current version of KO?

    thanks !

    Posted on December 24, 2011
  27. spacer zbrong

    Sorry another words:
    if we can use “jsRender” template with KO2, a sample please. thank you !

    Posted on December 24, 2011
  28. spacer Carl

    Is it possible to use both jQuery.tmpl and flow control bindings to assist with migrating away from jQuery.tmpl over time?

    Posted on December 25, 2011
  29. gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.