Rethinking Backbone.js View Rendering
elving.me
elving.me
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() }}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.
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.
Edited grammar.
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...
@$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.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.
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.
Agreed, my first thought was that there is no way to actively debug the template logic.
I summarized our new best practice here: http://tommyhallett.tumblr.com/post/37318050812/avoiding-ren...
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.
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.
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.
And when performance is a concern, you can't beat string interpolation within CoffeeScript heredoc strings.