lorenzoid
lorenzoid

Reputation: 1832

Render Backbone View on click (via Router push state)

I've got an app with 3 pages which I'm trying to render on click. The first page is a landing page. The other two should be rendered upon clicking a link. They are all contained inside of the same container div#modal-content

My HTML is as follows:

<script type="text/x-handlebars-template" id="landingPage">
    <div>
       <div class="auth-wrapper">
           <div class="logo">
               <img src="img/login/logo-landing.png"/>
           </div>
           <div class="to-auth-buttons-wrapper">
               <a class="btn-to-auth btn-login" href="#signup-page">Sign Up</a>
               <a class="btn-to-auth btn-signup" href="#login-page">Log In</a>
           </div>
       </div>
    </div>
</script>

My router function is as follows:

var Approuter = Backbone.Router.extend({
    initialize: function() {
        console.log('router initialized'); 
            Backbone.history.start({ pushState: true });   
    },

    routes: {
        '': 'main',
        'signup-page' : 'signup',
        'login-page' : 'login'
    },

    main: function() {
        this.landing = new LandingView({ el: $('#modal-content') });
        slider.slidePage(this.landing.$el);
    },

    signup: function() {
        this.signuppage = new SignUpView({ el: $('#modal-content') });
        console.log("LANDING VIEW: Signup clicked");
    },

    login: function() {
        this.loginpage = new LoginView({ el: $('#modal-content') });
        console.log("LANDING VIEW: Login clicked");
    }
});

And the view files are as follows:

var SignUpView = Backbone.View.extend({
    initialize: function() {
        this.render();
    },

    render: function() {
        var template = Handlebars.compile($('#signUpPage').html());

        this.$el.html(template);
    },
});

and

var LoginView = Backbone.View.extend({
    initialize: function() {
        this.render();
    },

    render: function() {
        var template = Handlebars.compile($('#loginPage').html());

        this.$el.html(template);
    },
});

Additionally, here are my templates:

<div id="modal-content">

  <script type="text/x-handlebars-template" id="landingPage">
      <div>
         <div class="auth-wrapper">
             <div class="logo">
                 <img src="img/login/logo-landing.png"/>
             </div>
             <div class="to-auth-buttons-wrapper">
                 <a class="btn-to-auth btn-login" href="#/signup-page">Sign Up</a>
                 <a class="btn-to-auth btn-signup" href="#/login-page">Log In</a>
             </div>
         </div>
      </div>
  </script>

  <script type="text/x-handlebars-template" id="signUpPage">
      <div>

         <div class="header">
             <a href="#" class="btn">Back</a>
         </div>
         <div class="auth-wrapper">


             <div class="logo">
                 <img src="img/login/logo-landing.png"/>
             </div>

             <form method="post" id="userSignUp">       
                 <input class="form-control input-signin" type="text" name="username" placeholder="Name" id="userName">
                 <input class="form-control input-signin" type="text" name="useremail" placeholder="Email" id="userEmail"> 
                 <input class="form-control input-signin" type="text" name="userpass" placeholder="Password" id="userPassword">

                 <a class="btn-to-auth btn-login js-btn-login">Sign Up</a>
             </form>
         </div>

      </div>
  </script>

  <script type="text/x-handlebars-template" id="loginPage">
      <div>
         <div class="header">
             <a href="#" class="btn">Back</a>
         </div>
         <div class="auth-wrapper">


             <div class="logo">
                 <img src="img/login/logo-landing.png"/>
             </div>

             <form method="post" id="userSignIn">       
                 <input class="form-control input-signin" type="text" name="useremail" placeholder="Email" id="userEmail"> 
                 <input class="form-control input-signin" type="password" name="userpass" placeholder="Password" id="userPassword">
                 <a class="btn-to-auth btn-login js-btn-login">Log In</a>
             </form>
         </div>

      </div>
  </script>

 </div>

My Problem Upon clicking the a#signup-page or a#login-page links, I can see the url change to "localhost/#signup-page", but the view is not being rendered.

BUT When I refresh the page at localhost/#signup-page or localhost/#login-page, I see the views are rendered.

Where am I going wrong?

Upvotes: 1

Views: 1053

Answers (1)

Claudio Santos
Claudio Santos

Reputation: 1317

Please take a look at the code above:

<html>

    <body>
        <div class="action">
            <a name="routeOne" href="#routeTwo">routeOne</a>
            <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
            <a name="routeTwo" href="#routeOne">routeTwo</a>
        </div>
        <div class="output"></div>


        <script type="text/javascript"  src="lib/jquery.js"></script>
        <script type="text/javascript"  src="lib/underscore.js"></script>
        <script type="text/javascript"  src="lib/backbone.js"></script>

        <script type="text/javascript">
            var Approuter = Backbone.Router.extend({
                initialize: function() {
                    console.log('router initialized'); 
                    Backbone.history.start({pushState:true});   
                },

                routes: {
                    '': 'main',
                    'routeOne' : 'routeOne',
                    'routeTwo' : 'routeTwo'
                },

                main: function() {
                    console.log("main");
                },

                routeOne: function() {
                    console.log("routeOne");
                },

                routeTwo: function() {
                    console.log("routeTwo");
                }
            });

            var routes = new Approuter();

        </script>
    </body>
</html>

Edit1: Differences between Routes and pushState

Backbone Routes enable you to monitoring hasChange history events (changes in url) and trigger some js code when found some change at url (http://localhost/backbone-test/#someRoute), That's amazing because we can trigger some complex actions done by user at your web site, just calling an url.

pushState enable you to hide this '#' hash and turn your url more readable, but as the backbone documentation said

"if you have a route of /documents/100, your web server must be able to serve that page, if the browser visits that URL directly."

Then, if you use pushState:true your url become more readable, http://localhost/backbone-test/#someRoute to http://localhost/backbone-test/someRoute but you need to create a back-end to answer directly access to you readable url.

When pushState is true and you call href="#someRoute" the browser understand this as a html anchor.

Upvotes: 1

Related Questions