Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need help understanding the basics of nested views in backbone

I've been doing a bunch of reading about nested views in backbone.js and I understand a good amount of it, but one thing that is still puzzling me is this...

If my application has a shell view that contains sub-views like page navigation, a footer, etc. that don't change in the course of using the application, do I need to render the shell for every route or do I do some kind of checking in the view to see if it already exists?

It would seem so to me if someone didn't hit the "home" route before moving forward in the app.

I haven't found anything helpful about this in my googling, so any advice is appreciated.

Thanks!

like image 542
Charles Avatar asked Mar 07 '13 17:03

Charles


1 Answers

Since your "shell" or "layout" view never changes, you should render it upon application startup (before triggering any routes), and render further views into the layout view.

Let's say your layout looked something like this:

<body>
  <section id="layout">
    <section id="header"></section>
    <section id="container"></section>
    <section id="footer"></section>
  </section>
</body>

Your layout view might look something like this:

var LayoutView = Backbone.View.extend({
  el:"#layout",
  render: function() {
    this.$("#header").html((this.header = new HeaderView()).render().el);
    this.$("#footer").html((this.footer = new FooterView()).render().el);
    return this;
  },

  renderChild: function(view) {
    if(this.child) 
      this.child.remove();
    this.$("#container").html((this.child = view).render().el); 
  }
});

You would then setup the layout upon application startup:

var layout = new LayoutView().render();
var router = new AppRouter({layout:layout});
Backbone.history.start();

And in your router code:

var AppRouter = Backbone.Router.extend({
  initialize: function(options) {
    this.layout = options.layout;
  },

  home: function() {
    this.layout.renderChild(new HomeView());
  },

  other: function() {
    this.layout.renderChild(new OtherView());
  }
});

There are a number of ways to skin this particular cat, but this is the way I usually handle it. This gives you a single point of control (renderChild) for rendering your "top-level" views, and ensures the the previous element is removed before new one is rendered. This might also come in handy if you ever need to change the way views are rendered.

like image 181
jevakallio Avatar answered Oct 21 '22 13:10

jevakallio