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:
... 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:
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.
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.
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.
Correct me if I'm wrong, but wouldn't the best place to combine and transform model data be in the model itself?
For trivial cases, this could be implemented in the model's 'defaults' function. (by computing the transformed field value in the function and returning a hash) If you forsee the need to update the value of the dynamic field in response to the client updating the model, you can perform the calculation again in the Model's 'validate' function.
Speaking from experience, logic in templates is convenient for trivial use cases, but can be very difficult to maintain once a project grows.
Exactly. We have a generic serialize() method in our models to do common toJSON. In item views, where performance is critical, the view itself transforms a subset of the models properties to JSON.
At tout.com, we were having timing issues with view rendering, for example if the view has a flash element in it and the $el isn't in the dom yet, you can't operate on the flash element in the render function.
I have a lot of canvas drawing going on in my app (charts) and ran into the same issue.
As you point out, appending the element to the DOM before everything is fully rendered can cause all sorts of re-drawing to go on. When that's a concern, I proactively set height/width dimensions on the element before adding it. In cases where that's problematic, I just have the render function of the view either update or remove the explicit height/width styling. That seems to help avoid the worst cases of redrawing/flicker.
That was our biggest peeve with Backbone views. We fixed it by having a `renderTo` method instead of `render`. Basically, insert the $el into the DOM first, then call render.
Another benefit to this approach is it makes replacing, disposing views, creating stacked views easy ... That is when renderTo tries to insert into a container and determines a view is already in place, it can call dispose or detach on the existing view. Much simpler than Marionette regions or other view management approaches.
Isn't this a bad idea outside of formatting a number as currency?
Also, Why not let JavaScript inject your model data directly into plain vanilla HTML templates? In other words, don't use any template tags at all. These 2 projects are really piquing my interest.
I absolutely love Backbone, but the biggest issue for me has been dealing with complex logic in the templates. Most of the time now my render() method just builds the darn elements right in there.
as long as it is just a view and not data manipulation, what is wrong with that? You do not have to have template at all. What if your view is list generator with classes? Why having template at all?
I've found it useful to abstract away render and work with before/afterRender hooks instead. I still call render which has a base implementation that calls the template, but instead of passing just the model or the model's JSON, I pass a context object that I can build up to suit my needs. This way every template is dealing with the same thing, and the whole mechanism is extensible.
[+] [-] jashkenas|13 years ago|reply
[+] [-] csallen|13 years ago|reply
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.
[+] [-] clintjhill|13 years ago|reply
Edited grammar.
[+] [-] georgedyer|13 years ago|reply
[+] [-] elving|13 years ago|reply
[+] [-] bjhoops1|13 years ago|reply
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.
[+] [-] ronaldj|13 years ago|reply
[+] [-] unknown|13 years ago|reply
[deleted]
[+] [-] condiment|13 years ago|reply
For trivial cases, this could be implemented in the model's 'defaults' function. (by computing the transformed field value in the function and returning a hash) If you forsee the need to update the value of the dynamic field in response to the client updating the model, you can perform the calculation again in the Model's 'validate' function.
Speaking from experience, logic in templates is convenient for trivial use cases, but can be very difficult to maintain once a project grows.
[+] [-] clschnei|13 years ago|reply
Agreed, my first thought was that there is no way to actively debug the template logic.
[+] [-] account_taken|13 years ago|reply
[+] [-] catshirt|13 years ago|reply
[+] [-] tomhallett|13 years ago|reply
I summarized our new best practice here: http://tommyhallett.tumblr.com/post/37318050812/avoiding-ren...
[+] [-] numbsafari|13 years ago|reply
As you point out, appending the element to the DOM before everything is fully rendered can cause all sorts of re-drawing to go on. When that's a concern, I proactively set height/width dimensions on the element before adding it. In cases where that's problematic, I just have the render function of the view either update or remove the explicit height/width styling. That seems to help avoid the worst cases of redrawing/flicker.
[+] [-] account_taken|13 years ago|reply
Another benefit to this approach is it makes replacing, disposing views, creating stacked views easy ... That is when renderTo tries to insert into a container and determines a view is already in place, it can call dispose or detach on the existing view. Much simpler than Marionette regions or other view management approaches.
[+] [-] heme|13 years ago|reply
Also, Why not let JavaScript inject your model data directly into plain vanilla HTML templates? In other words, don't use any template tags at all. These 2 projects are really piquing my interest.
http://blog.nodejitsu.com/micro-templates-are-dead
https://github.com/leonidas/transparency/wiki/Frequently-Ask...
Side benefit is that you can still pre/hybrid render from the server in whatever language you like.
[+] [-] jscheel|13 years ago|reply
[+] [-] hippich|13 years ago|reply
[+] [-] ktusznio|13 years ago|reply
https://gist.github.com/ktusznio/5119318
[+] [-] bjhoops1|13 years ago|reply