Blog Archives

A new variable for Knockout.js bindings – the DOM element

When writing knockout bindings it can sometimes be handy to reference the DOM element you are writing the element for. As an example, you may want information on a DOM property or for development reasons simply want to show the id.

I tweaked Knockout to support using an $element special variable last year, but hadn’t decided to submit it yet.  Based on the discussion in knockout issue 176 I decided to clean it up and submit it as knockout pull request 474. Mbest also updated it to work with the latest knockout changes.

Usage is simple:

<div data-bind='text: $element.tagName'></div>

Enjoy!

As an aside, I’m going to be presenting on Derby and Meteor at the NodeDC Meetup on 5/16. If you are interested in Node or just want to connect with some cool DC coders stop by!

Enabling Knockout.js to work across iframes

If you haven’t checked out Knockout yet, I highly recommend it.

Knockout allows you to create declarative bindings in your HTML that map to your underlying model’s properties. The nice thing about the bindings being in HTML is that you and your designer team can work in real HTML.

But Knockout’s real magic comes from its dependency tracking. When bound model properties change, Knockout magically updates the bound parts of the HTML that need it. It’s an approach I have used many times that gives you the real benefits of MVC by allowing the view to bind to the model rather than the other way around.

We wrote something similar in Digitalk Smalltalk back in the 90s, and then VisualWorks Smalltalk introduced Aspect Adaptors baked right in. In Knockout these model property trackers are called Observers. It also has something called a Dependency Observer that tracks any model properties accessed during a function call (for example getting the list of users), it then automatically creates observers on those properties. Very cool.

One problem with the current version of Knockout is that there are still a few hurdles preventing it from working across frames or windows: it uses a global state to do its Dependency Observer magic, it does identify class checking (which fails across frames), and it does some things relative to the window the code was loaded into rather than the current element’s window. I have written a couple of patches that cover most of these cases and have submitted a pull request to Steve Sanderson.

Update 3/21/12

After many tweaks and discussions my cross-frame changes have been accepted into Knockout 2.10. See issue 405 for details.

IntelliJ IDEA Code Completion for Knockout data-bind attributes

I’m a fan of Knockout. Among other awesome features, it allows you to create custom data bindings right inside your HTML using a data-bind attribute. The value of this attribute is actually a piece of JavaScript code that is executed each time the bindings are evaluated. These bindings can be simple or quite complex. Here is a simple example:

</pre>
<div data-bind="css: { profitWarning: currentProfit() < 0 }">Profit Information</div>
<pre>

Unfortunately, if you’re working with IntelliJ IDEA (WebStorm/RubyMine) you won’t get all of its JavaScript magic for the data-bind value because it thinks it’s looking at an HTML attribute string, so no code completion, etc.

But there is a way to fix this. IntelliJ supports something called Language Injection (originally called IntelliLang) to detect code fragments within another language, such as JavaScript code inside an HTML script element. Even better, IntelliJ lets you define your own Language Injections. So let’s create one for the Knockout data-bind attribute. It’s pretty straightforward to do, here are the steps…

  • In your project settings (even though Language Injections are global, they are defined in the project settings) select Language Injections
  • Click New then XML Attribute Injection
  • Then fill it out the dialog as follows (see screenshot below)
    • ID is the language type (JavaScript in our case)
    • Prefix/Suffix are used to make the data-bind string valid JavaScript code
    • Local Name indicates the attribute name where the Language Injection applies.

And now you will get all the IntelliJ goodness you love when editing your Knockout data-bindings like code completion, syntax/error highlighting, docs, and navigation!

You don’t have to stop with Knockout of course. You can also create more complicated injection rules using XPath or IntelliJ internal “Program Structure Interface Patterns,” which allow you map to the language structure itself.

I’ve created a few for other cases as well, which I’d be happy to share in another blog post if there’s enough interest. Just let me know in the comments.