9 ms·
Rethinking Backbone.js View Rendering
- jscheel 14y agoI 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 14y agoas 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 14y agoIt can get pretty messy at times.
- georgedyer 14y agotry CoffeeKup: https://github.com/mauricemach/coffeekup https://github.com/mauricemach/coffeekup or Teacup: http://goodeggs.github.com/teacup/ http://goodeggs.github.com/teacup/
- jscheel 14y agoI used coffeekup back in the day, but I just can't stand the jade-style declarative html. I also used eco for a while, but it got pretty messy too. I'm picky, I know :)
- account_taken 14y agoTry https://github.com/mgutz/funcd 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 14y agoYep, 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.
- jeffmess 14y agoWhy can't people just use regular HTML for markup? Coffeescript is beautiful when you are composing short succinct functions but this just looks like more work for my brain.
- catshirt 14y agoOP started using Handlebars helpers. there is no "rethinking" happening here and it hardly even pertains to Backbone.
- condiment 14y agoCorrect 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 14y ago"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.
- account_taken 14y agoExactly. 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.
- tomhallett 14y agoAt 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-render-timing-issues-in-backbone http://tommyhallett.tumblr.com/post/37318050812/avoiding-ren...
- numbsafari 14y agoI 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 14y agoCool approach! I'll keep that in mind.
- account_taken 14y agoThat 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.
- jashkenas 14y agoYes, 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 14y agoI 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 14y agoThe "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.
- deleted 14y ago[deleted]
- bjhoops1 14y agoI 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/ http://brettjonesdev.com/on-templating-in-backbone/
- heme 14y agoIsn'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 http://blog.nodejitsu.com/micro-templates-are-dead https://github.com/leonidas/transparency/wiki/Frequently-Asked-Questions 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.
- ktusznio 14y agoI'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 https://gist.github.com/ktusznio/5119318