7

In most BackboneJS examples I've seen, parent views call the render() function on child views. This seems a little odd to me. Maybe it's completely for optimization or something, but I don't see why the optimization couldn't take place within the child view itself. Shouldn't the child view be responsible for calling its own render()? It seems like in all my views I end up with something like:

initialize: function() {
    this.render();
}

Also, if my parent view updates the child view's model property, how is the child supposed to know that the model changed (and therefore render() needs to be called)? I assume in this case the parent is forced to call the child's render(). Although it's somewhat inferred, why should the parent need to know that the child needs to re-render when its model is changed? It seems like calling the render function of the child view is outside of the parent view's domain.

Aaronius
  • 4,936
  • 6
  • 31
  • 40

1 Answers1

13

Like pretty much everything Backbone-related, this is a pretty subjective question. But here are a few reasons you might want the parents to render:

  • It's perfectly reasonable to think that the parent view might need to make sure that the child views are rendered before the rest of the rendering takes place. For example, the parent might need to size a container element based on the size of its children, or show a container only once its contents are rendered by the child views.

  • Your "render on initialize" pattern only works if you don't need to do other things first - for example, one common pattern is for the view to bind to the model's change event, call this.model.fetch(), and render in the callback. In this case, especially if you care about execution order of the different renders, it's nice to have a single event listener on the parent and then have the parent deal with rendering children, rather than having bindings with every child, even though those children won't be calling fetch().

  • Also, having the parent render the children doesn't preclude the children re-rendering themselves, e.g. in response to more specific events. Having the parent call child.render() just helps to ensure that this has happened by the time the parent is finished rendering.

It's also worth noting that views have a default no-op for render. So the parent can call render() on the child without having to be sure it'll do anything.

In answer to "what if the parent changes the child's model?", one option is, don't do that - always create a new child for each new model. But that might not fit your architecture - in which case having the parent responsible for re-rendering the child makes perfect sense.

nrabinowitz
  • 55,314
  • 10
  • 149
  • 165
  • Thanks for responding! Regarding bullet 1: If the child always re-renders itself immediately after init, model events, DOM events, etc. it should always be ready for the parent view to do anything it wants with it, no? Bullet 2: I'd personally rather each child watch the model as the parent shouldn't have to know that the children care about the model. Bullet 3: See response to bullet 1. Creating a new view just because the model is changing seems inefficient. – Aaronius Oct 11 '11 at 22:28
  • 1
    Well, as I said, it's subjective - Backbone doesn't really define a "right" way to do things. But personally, I prefer to assume that parents are aware of and responsible for their immediate children. – nrabinowitz Oct 11 '11 at 22:43
  • Also, Bullet 3 - it really depends on the app. Maybe you can cache the previous view for later, for example. – nrabinowitz Oct 11 '11 at 22:44
  • Thanks for your insight. Marking as correct. I'd love to hear if others have patterns of doing these things. – Aaronius Oct 11 '11 at 23:21
  • 1
    I agree with @nrabinowitz's answer, but I don't quite know what you mean by "model change". Do you mean the model is replaced with another model? If that's the case, then refer to this question: http://stackoverflow.com/questions/7567404/backbone-js-repopulate-or-recreate-the-view. Or do you mean that the attributes of your model changed? If so, then you can add this line to your child's initialize method: this.model.bind('change', this.render, this); Child will re-render when model content changes. – Johnny Oshika Oct 12 '11 at 06:40