Skip to content

Instantly share code, notes, and snippets.

@justinbmeyer
Created June 14, 2012 06:35
Show Gist options
  • Save justinbmeyer/2928408 to your computer and use it in GitHub Desktop.
Save justinbmeyer/2928408 to your computer and use it in GitHub Desktop.
Why do you like Handlebars (and concerns about live-binding)

I'm considering adding an alternative to CanJS's EJS live-binding system. I really like EJS, it's extremely powerful, but ugly to look at. So, I'm trying to create a better mouse-trap.

Currently, the most popular mouse-trap seems to be Handlebars. What do you like about it?

  • Syntax, or
  • Prepared data

Syntax

Handlebars uses {{}} for insertion and {{#}} and {{/}} for widgets and control structures.

Prepared data

All data must be passed to handlebars (except accessed through a helper). You can not seemingly call helper methods that read data like {{person.age()}}. This limits logic that can be performed in the template (although a helper can still do pretty much anything).

Concerns about live-binding and handlebars

I'd like to learn what people like about handlebars and use that in the design of the alternative templating language. But, there's two issues I would have to overcome:

Prepared Data

Prepared data is something that has been strongly promoted on the server and it also is being promoted on the client. I don't consider it as much an imperative on the client. I've never seen anyone fire an ajax call in a template. The data is always prepared, it's just accessed through the model or other helpers.

Needing prepared data makes doing something like http://jsfiddle.net/qYdwR/36/light/ with Handlebars more difficult to write. You'd have to create a computed property that is the date merged with this updating time observable.

With EJS, you can just write a function and anything that uses it becomes live.

Limited "helpers" (this is no longer a concern ... Handlebars must support this)

I don't think it's possible in Handlebars, but EJS supports ERB-style sub template helpers (if you wanted to build them) like:

<%== columns(items, 4, function(item){ %>
  <li><%= item.attr('name') %></li>
<% }) %>

Notice that the function(item){ ... } is actually a template that is called out to by the columns helper implemented like:

columns = function(items, num, template){
    var cols = new Array(num);
    items.forEach(function(item, i){
      if( ! cols[i%num] ) { 
        cols[i%num] = "";
      }
      cols[i%num] += template(item)
    });
    return "<ul>"+cols.join("</ul><ul>")+"</ul>";
}

And this would also instantly become live.

@justinbmeyer
Copy link
Author

The function stuff certainly makes sense ... you see a different type and get a value from it slightly differently. I don't think seeing an observe and getting a value differently (and of course hooking up live-binding) violates the ideas behind handlebars (especially as this is almost certainly what Yehuda is doing).

But, if you are ok with functions being treated differently, I've just added a compute method for CanJS:

canjs/canjs@8eb7847

What handles list binding?

I think maybe how EJS does it's magic isn't clear (because it's so powerful it might seem like magic). There's really nothing special that "handles" list binding. It's just the part of code that updates an HTML chunk listed above at: https://github.com/jupiterjs/canjs/blob/master/view/ejs/ejs.js#L329

The secret is that can.Observe.List changes it's length property when items are removed or added and can.Observe.List.prototype.each calls this.attr('length'). So a block like:

<% list.each(function(){ %>
  CONTENT
<% }) %>

is just html getting updated that is live-bound to the list's length.

@justinbmeyer
Copy link
Author

@iamnoah
Copy link

iamnoah commented Jun 18, 2012

Right, that makes sense, you would just use a DOM diff for everything. can.compute will be very helpful.

The flag to turn it off though is going to be essential, and those of us who need to upgrade will need it per view() call. Right now we have a lot of manual update code that could interfere with live binding. That's why it would be better for us to have a helper instead.

@iamnoah
Copy link

iamnoah commented Jun 19, 2012

As promised, here is our plugin: https://github.com/Spredfast/jmvc-bind-handlebars

It's a different approach, but it gets us close without too much code.

@tommymorgan
Copy link

Justin and Noah, I am very sorry, but I had to make the repo private until we attach a license to the code. I will try to make sure this happens quickly so I can make it public again.

@tommymorgan
Copy link

It's public again. Sorry for the disruption.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment