swayziak
swayziak

Reputation: 353

The backbone router isn't working properly

I'm building a simple backbone app that have 4 routes: home, about, privacy and terms. But after setting the routes I have 3 problems:

The "terms" view isn't rendering;

When I refresh the #about or the #privacy page, the home view renders after the #about/#privacy view

When I hit the back button the home view never renders. For example, if I'm in the #about page, and I hit the back button to the homepage, the about view stays in the page

I don't know what I'm doing wrong about the 1st problem. I think that the 2nd and 3rd problem are related with something missing in the home router, but I don't know what is.

Here is my code:

HTML

<section class="feed">

    <script id="homeTemplate" type="text/template">

        <div class="home">
        </div>

    </script>

    <script id="termsTemplate" type="text/template">

        <div class="terms">
        Bla bla bla bla
        </div>

    </script>   

    <script id="privacyTemplate" type="text/template">

        <div class="privacy">   
        Bla bla bla bla
        </div>

    </script>

    <script id="aboutTemplate" type="text/template">

         <div class="about">
         Bla bla bla bla
         </div>

    </script>

</section> 

The views

app.HomeListView = Backbone.View.extend({
    el: '.feed',

    initialize: function ( initialbooks ) {
         this.collection = new app.BookList (initialbooks);
         this.render();
    },

    render: function() {
         this.collection.each(function( item ){
         this.renderHome( item );
         }, this);
    },

    renderHome: function ( item ) {
         var bookview = new app.BookView ({
         model: item
         })
         this.$el.append( bookview.render().el );
         }  });

app.BookView = Backbone.View.extend ({
    tagName: 'div',
    className: 'home', 

     template: _.template( $( '#homeTemplate' ).html()),

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

app.AboutView = Backbone.View.extend({
     tagName: 'div',
     className: 'about',

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

     template: _.template( $( '#aboutTemplate' ).html()),

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

 app.PrivacyView = Backbone.View.extend ({
     tagName: 'div',
     className: 'privacy',

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

     template: _.template( $('#privacyTemplate').html() ),

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

 app.TermsView = Backbone.View.extend ({
     tagName: 'div',
     className: 'terms',

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

     template: _.template ( $( '#termsTemplate' ).html() ), 

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

And the router:

var AppRouter = Backbone.Router.extend({
     routes: {
         '' : 'home',
         'about' : 'about',
         'privacy' : 'privacy',
         'terms' : 'terms'
     },

     home: function () {
         if (!this.homeListView) {
             this.homeListView = new app.HomeListView();
         };
     },

     about: function () {
         if (!this.aboutView) {
             this.aboutView = new app.AboutView();
        };
         $('.feed').html(this.aboutView.el);
     },

     privacy: function () {
         if (!this.privacyView) {
             this.privacyView = new app.PrivacyView();
         };
         $('.feed').html(this.privacyView.el);
     },

     terms: function () {
          if (!this.termsView) {
             this.termsView = new app.TermsView();
         };
         $('.feed').html(this.termsView.el);
     }
 })

 app.Router = new AppRouter();
 Backbone.history.start(); 

I'm missing something but I don't know what.

Thanks

Upvotes: 3

Views: 235

Answers (2)

ebohlman
ebohlman

Reputation: 15003

In addition to everything suggested by Rayweb_on, remove the call to render from the initialize methods of AboutView, PrivacyView and TermsView and in your route functions, replace $('.feed').html(this.aboutView.el);, etc. with $('.feed').html(this.aboutView.render().el);, etc.

Also, define a variable in your router called currentView or something like that and set it to whatever view your route functions choose. In each route function, check if it's been set and if so, call remove() on it before rendering the new view. These changes should keep previously-rendered views from stepping on new ones and make sure that the newly-rendered view is up-to-date.

Upvotes: 2

Rayweb_on
Rayweb_on

Reputation: 3727

I think you need to move your script templates out of your .feed html element, when you render the HomeListView view it will remove everything inside its el, then the script templates will be unavailable to the other views that you are calling iside of the HomeListView.

<section class="feed">



</section>
<script id="homeTemplate" type="text/template">

    <div class="home">
    </div>

</script>

<script id="termsTemplate" type="text/template">

    <div class="terms">
    Bla bla bla bla
    </div>

</script>   

<script id="privacyTemplate" type="text/template">

    <div class="privacy">   
    Bla bla bla bla
    </div>

</script>

<script id="aboutTemplate" type="text/template">

     <div class="about">
     Bla bla bla bla
     </div>

</script> 

also you are missing a colon in the render function for the termsView

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

Upvotes: 2

Related Questions