cl0udw4lk3r
cl0udw4lk3r

Reputation: 2733

Backbone View: Cannot append a view to a previously rendered view

Here it is my backbone code

app.js

window.App = {
Models: {},
Views: {}
};

window.Template = {};

app/router.js

App.Router = Backbone.Router.extend({

  initialize: function () {
    Backbone.history.start({pushState: true});
    App.layout = new App.Views.Layout();
    App.layout.render();
    $('#app').append(App.layout.el);
  },

  routes: {
    '': 'index'
  },

  index: function () {
     console.log('index routed.');
     App.home = new App.Views.Home();
     App.home.render();
     $('#content').html(App.home.el);
  }
});

app/templates.js

Template.layout = _.template(
  "<header id=top-bar>"+
  "<nav id=user-panel>"+
  "<ul>"+
  "<li><a class=login href=#>Login</a></li>"+
  "<li><a class=register href=#>Registrati gratis</a></li>"+
  "</ul>"+
  "</nav>"+
  "</header>"+
  "<div id=wrapper>"+
  "<section id=mid-bar>"+
  "<a id=logo href=#><img src=public/img/logo.png></a>"+
  "</section>"+
  "<section id=content>"+
  "</section>"+
  "</div>"
);

Template.home = _.template("Benvenuto in Virtualmix");

app/views/layout.js

App.Views.Layout = Backbone.View.extend({
  id: 'container',

  template: Template.layout,

  render: function () {
    this.$el.html(this.template);
  }
});

app/views/home.js

App.Views.Home = Backbone.View.extend({

  tagName: 'p',

  template: Template.home,

  render: function () {
    this.$el.html(this.template);
  }
});

and finally my main.js

$(document).ready(function () {
  App.router = new App.Router;
});

well, the layout view (initialized from the router initialize function...) is correctly rendered, but the home view, initialized and rendered from the index function, seems to output nothing on my previously generated layout (i want to nest home on the #content element generated by the layout...).

I think it's a JQuery problem, but i can't figure out how and why...

Upvotes: 0

Views: 159

Answers (1)

jevakallio
jevakallio

Reputation: 35890

The problem is that you're calling Backbone.history.start() too soon. When you start the history, the route is triggered immediately, at which point your LayoutView is not yet rendered, and there is no #content element on the page.

The Backbone docs say:

During page load, after your application has finished creating all of its routers, be sure to call Backbone.history.start() ... [emphasis mine]

I like to still have my main ("app") router be in charge of starting the history, so I usually create a start method on the router:

AppRouter = Backbone.Router.extend({
  start: function() {
    Backbone.history.start();
  },
  //...
});

And call it like so:

var appRouter = new AppRouter();
var otherRouter = new OtherRouter(); // if you have any
appRouter.start();

Upvotes: 1

Related Questions