

Rethinking Backbone.js View Rendering - elving
http://elving.me/post/44859632208/rethinking-backbone-js-view-rendering

======
jashkenas
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() }}

~~~
csallen
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.

~~~
jashkenas
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.

------
condiment
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.

~~~
clschnei
"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.

------
catshirt
OP started using Handlebars helpers. there is no "rethinking" happening here
and it hardly even pertains to Backbone.

------
tomhallett
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 summarized our new best practice here:
[http://tommyhallett.tumblr.com/post/37318050812/avoiding-
ren...](http://tommyhallett.tumblr.com/post/37318050812/avoiding-render-
timing-issues-in-backbone)

~~~
numbsafari
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.

~~~
tomhallett
Cool approach! I'll keep that in mind.

------
heme
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.

<http://blog.nodejitsu.com/micro-templates-are-dead>

[https://github.com/leonidas/transparency/wiki/Frequently-
Ask...](https://github.com/leonidas/transparency/wiki/Frequently-Asked-
Questions)

Side benefit is that you can still pre/hybrid render from the server in
whatever language you like.

------
jscheel
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.

~~~
hippich
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?

~~~
jscheel
It can get pretty messy at times.

~~~
georgedyer
try CoffeeKup: <https://github.com/mauricemach/coffeekup> or Teacup:
<http://goodeggs.github.com/teacup/>

~~~
account_taken
Try <https://github.com/mgutz/funcd>. It's straight up CoffeeScript functions
patterned after Markaby, Erector. Other CoffeeScript templates we tried did
funky things with the context and closures didn't work as expected.

And when performance is a concern, you can't beat string interpolation within
CoffeeScript heredoc strings.

~~~
jscheel
Yep, that's usually how I start my render() method (using triple-quote
strings). Then I wrap it in jquery and do dom manipulation on it.

------
ktusznio
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.

<https://gist.github.com/ktusznio/5119318>

------
bjhoops1
I find it easier to use Handlebars first, then fall back on _.template() when
you need logic in your templates. It's easy : <http://brettjonesdev.com/on-
templating-in-backbone/>

