Hacker News new | ask | show | jobs
by jashkenas 4844 days ago
Yes, absolutely pass models directly to your views. That's what they're for, after all -- keeping together a handy bunch of methods that can display your data in ways that are terrifically useful for a view to show:

    account.statusWarning()

    document.listOfCollaborators()

    photo.similar.first().publicUrl()
... and so on. But by all means, don't use Handlebars to do it. Use a templating engine that allows real logic, and rest easier at night. Handlebars is set up as faux-logicless templating -- A wolf in Mustache.js' clothing. Having to add Handlebars helpers just to be allowed to call a "method" (as shown in the blog post) is pretty silly example of forced indirection, no? Much more straightforward with embedded JavaScript:

    {{ model.getFullName() }}
6 comments

I recently started learning EmberJS which forces the user of Handlebars. I thought maybe I was crazy, or maybe I was missing something, but your comment makes me feel a little bit more sane.

Why oh why would you ever use Handlebars over, say, Underscore's templates which allow actually logic? In my (admittedly limited) experience, both choices are equally as simple when writing simple templates, but Handlebars is a colossal pain in the ass when trying to do something significant.

The "structured" nature of Handlebars is important if you're using Ember, because it's set up specifically to allow it to parse the interpolations in your templates and determine what attributes you're binding, and so on. But if you're not using Ember, a "colossal pain in the ass" sounds about right.

Do yourself a favor and use true logic-less templates (Mustache, in all of its myriad flavors) if you really believe in that sort of thing. Or make life easy on yourself and use a programming language you already know. Embedded Ruby, embedded JavaScript, embedded PHP (the only kind there is) -- all have the virtue of allowing as much or as little code as you need and want, and allow you to do whatever you need to get the job done.

I would have the opinion that you don't mean "real logic" as much as you mean "model data". In other words if you follow the examples you give, I wouldn't see any reason that the model would not have those fields accessible directly or via a standardized "get" as opposed to direct function calls. I would argue that "real logic" in your view/template is a "real bad" idea.

Edited grammar.

I'm afraid I do mean "real logic" -- in terms of "real function calls", or "real math", or whatever else you might want to do. Let me imagine a few more examples:

    inflector.addCommas(arrayOfNames)

    document.publicNoteCount + document.privateNoteCount

    format.quote(email.selectedText())
... you always can stuff all of those things into an arbitrary "viewmodel" JSON object somewhere else outside of the template, but it's frequently clearer and more convenient just to do it where it's needed -- instead of enforcing an extra layer of indirection for no real reason -- by passing around models directly.

I guess I feel somewhat strongly about this because having multiple sources for the same truth is what gets people into trouble so often with client-side apps. (Where by a "truth" I mean something like: "What are the names of the collaborators on this document".) Having that data in your model and then again in your viewmodel, and some parts of your app access it over here, and your templates access it over there, is exactly that sort of unnecessary duplication...

We agree on having a single source of truth. I'm arguing for it to be derived in a controller and not in a view.
Then the controller becomes a second source of truth, no?
I'm a big fan of adding a CoffeeKup template method right in the view. Then just call

    @$el.html coffeekup.render @template, @
in my render function. But I suppose that gives up keeping the html markup separate. For ui components, though, it just makes sense to me to keep the structure bundled with the functionality that way.
Makes sense. The idea of using Handlebars instead of embedded Javascript is that the template can't actually change the model, just get data from it, so there's no real logic on the template. Of course this is all theory, as I said in the blog post, it was just an idea. Once I use this approach, I can definitely state the pros and cons.
Yes, Handlebars is explicitly designed for logicless templating. If you need real logic in your View (which I might add is often a good time to step back and possibly refactor your solution), you can always fall back on Underscore's templating.

I frequently do this in my apps - I use Handlebars by default, but fall back on _.template() any time my view's absolutely have to have logic in them.

Since Backbone already depends on Underscore, it's harmless in terms of introduced dependencies.

You can call a method with Mustache. You don't event need Handlebars to do that.