Site Meter
 
 

Knockout 2.0.0 released

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?

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 Smile

47 Responses to Knockout 2.0.0 released

  1. J. Gagnon

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

    Thanks !
    J

  2. 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.

  3. 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!

  4. I agree with the giant laughing pear thing!

  5. SI Hayakawa

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

  6. Alagesann Palani

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

  7. Jeremy

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

  8. 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. !!!

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

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

  11. Harsha

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

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

  12. Xin SU

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

    Thank you all the community members, Knockout is excellent.

  13. zbrong

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

  14. Hashname

    Thank you Mr.Anderson :)

  15. 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 “

  16. 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 “

  17. Steve

    Hi Giles – sorry about the blog eating your tags… :( 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: http://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!

  18. giles bradshaw

    Thanks for that Steve.

  19. Fantastic job Steve!

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

    Next up … containerless bindings for all built in binding types :-)

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

  20. Stefan

    Great! Thanks for all the effort!

  21. 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

  22. dariob

    the wait is over! Thank you so much!

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

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

    Please keep up the great work!

  25. 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 !

  26. zbrong

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

  27. Carl

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

  28. The selectors are to bindingConventions only support selectors by id and class ?

  29. ms440

    Throttling! Hurray!

    Just replaced my homebrew implementation of this functionality (ugly, ugly) in our flagship project with KO 2.0. Works like a charm, nice and easy.

    Thanks a million!

  30. Pingback: JavaScript Weekly #58 | island205

  31. dencio tadpole

    Hi Scott,

    Thanks for the great post and great JS library.

    I have a question though, if you dont mind. In foreach binding, how can we display the key of json array in addition to the value?

    Thanks.

  32. Ian Turner

    Thanks Steve – glad to see you’re moving things on a little (or a lot, in this case).

    However, in terms of the “breaking changes”, surely you could have defined

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

    … and made it a non-breaking change?

    On a side issue, is anyone experiencing issues with any of the try…finally blocks in Knockout.js (e.g. in the evaluate() function of dependentObservable) with IE8? I find that without a “catch” block, they cause an exception (strangely, only a change to the code in my Knockout.js based grid component has highlighted this, but it appears to be an IE8 issue nontheless, reporting “expected identifier” at the { after the finally)

    Thanks.

  33. Alagesan Palani

    Hi Steve,
    How to access the $Index( just like $data) of an array using knockout 2 foreach statement.

  34. zbrong

    Hi steven
    Good new chinese dragen year!
    knockoutjs is a great framework, it is a very nice tool to write viewModel and can towWay bind to view conveniently. I very like it!
    RIA/JS can listen the data state, we can use this feature to commit changes and visualize data.
    can we use RIA/JS with knockoutjs, make RIA/JS to listen the viewModel’s data?

  35. Dawid Ciecierski

    You know what? I haven’t been this excited about a framework since I first heard of and seen MVC1 in action. Thank you for making the world a better place!

  36. Narasiman

    Hi Steaven,

    Kindly can I have your Jquery files that you have used.

    Also Kindly can I know how you have used the Jquery plugin.

    Thanks,
    Narasiman J.

  37. Alex Karamushko

    Hello Steve,

    What are your plans about custom binding providers in general? And specifically example in your blog post (and on jsfiddle) has actual custom binding provider (in a separate file) – any plans to make it official KO plug in, along with ko mapping? Any plans to publish it on github as a public code? Any plans to keep it compatible with future KO releases?
    and Thank You Much for the KO!!!
    –Alex

  38. Pierre Constantial

    Thanks for the great job. Just to make it even more perfect, I want to point out that knockout-2.0.0.js is using different line endings: dos for the comments at the top and the function declaration, unix for the minified code. Some tools are complaining about it (VCS).

    Thanks again!

  39. zbrong

    Hi steve
    the “for” attribute of can’t be bind.
    may u have a try please ?

  40. zbrong

    Hi steve
    the “for” attribute of <label> can’t be bind.
    may u have a try please ?

  41. miran

    I am using KO already and after seeing the highlights and features given by you is really awesome. I like the main feature “Control flow bindings”. I think we should try it.

    dog boarding calgary prices

  42. I haven’t been this excited about a framework since I first heard of and seen MVC1 in action. Thank you.

    Best Regards
    Gary
    Web Design

  43. Srinivasa Kosuri

    Hi Steven,

    Love your blogs and thanks for your efforts. Can you please tell me how to make input in upper case? I dont want to let users to enter lowercase while entering list of items.

  44. Bill

    This line of code in DeliveriesViewModel.js is failing:

    self.deliveriesForCustomer =
    self.deliveries.groupBy(“Customer”);

    I get the error message: “Microsoft JScript runtime error: Object doesn’t support property or method ‘groupBy’.”

    Any ideas anyone? Thanks!

  45. Liam

    Thanks Steve, Knockout is great, i use it every day, and it saves me loads of time. A great library.

    And i hope Sheffield Wednesday go up this season, via the playoffs of course; 2nd spot is for the Blades ;)

  46. Hi Steve,

    Thanks for bringing Knockout to the world. I built a companion library for KO called TKO (ha ha) and I was hoping you could weigh in. I’m using TKO heavily in a project I’m doing now, and it’s saved me a ton of time, and I feel that it’s more flexible than stuff like backbone.js and ember.js. See the github link above.

    Thanks,
    Floyd