Question

I have created a small jsfiddle which doesn't perform the login right using ember 1.5 and handlebars 1.3. The login controller holds a property "isLogin" which is set to true. But why does afterwards none of the other routes and templates takes notice of this change?

    <script type="text/x-handlebars">
    {{#if controllers.login.isLogin}}
    <div class="container">
      <div class="navbar">
        <div class="navbar-inner">
          <a class="brand" href="#">Ember Digest</a>
          <ul class="nav pull-right">
            <li>{{#link-to 'articles'}}Articles{{/link-to}}</li>
            <li>{{#link-to 'photos'}}Photos{{/link-to}}</li>
            <li>{{#link-to 'login'}}Login{{/link-to}}</li>
          </ul>
        </div>
      </div>
      {{outlet}}
    </div>
    {{/if}}
    {{render 'login' controllers.login.content}}
</script>

  <script type="text/x-handlebars" data-template-name="articles">
    <h2>Articles</h2>
  </script>


  <script type="text/x-handlebars" data-template-name="login">
    {{#if isLogin}}
      <p>You are already logged in!</p>
    {{else}}
      <form class="form-inline" {{action login on="submit"}}>
        <h2>Log In</h2>
        {{input class="btn" type="submit" value="Log In"}}
      </form>
      {{#if errorMessage}}
        <div class="alert alert-error">{{errorMessage}}</div>
      {{/if}}
    {{/if}}
  </script>

and the js

App = Ember.Application.create();

// Routes
App.Router.map(function () {
    this.route('articles');
    this.route('photos');
    this.route('login');
});

App.LoginRoute = Ember.Route.extend({
    renderTemplate: function () {
        this.render('login', {
            into: 'application',
            outlet: 'login'
        });
    }
});

App.AuthenticatedRoute = Ember.Route.extend({

    beforeModel: function (transition) {
        if (!this.controllerFor('login').get('isLogin')) {
            this.redirectToLogin(transition);
        }
    },

    redirectToLogin: function (transition) {
        alert('You must log in!');
        var loginController = this.controllerFor('login');
        loginController.set('errorMessage', 'Login first');
        this.transitionTo('login');
    }
});

App.ApplicationRoute = Ember.Route.extend({
    beforeModel: function (transition) {
        if (!this.controllerFor('login').get('isLogin')) {
            this.transitionTo('login');
        }
    }
});

App.LoginController = Ember.Controller.extend({
    isLogin: false,
    errorMessage: '',
    actions: {
        login: function () {
            alert("login");
            this.set('isLogin', true);
            this.transitionToRoute('articles');
        }
    }
});

App.ArticlesRoute = App.AuthenticatedRoute.extend({
    needs: 'login'
});

App.ApplicationController = Ember.Controller.extend({
    needs : 'login'
});
Was it helpful?

Solution

It's a bit hard for me to test right now, but I think you're running into issues because you're reaching down the route hierarchy. For the most part, Ember controllers/routes are allowed to access properties of their parent objects, but not their children objects. (Which makes sense, because it's possible for the parent to be active but not the child.)

I think that instead of having the isLogin property in LoginController, put it in ApplicationController. Then, in the places you need it, create an alias:

App.ApplicationController = Em.ObjectController.extend({
    isLogin: false
});

App.LoginController = Em.ObjectController.extend({
    needs: ['application'],
    isLogin: Em.computed.alias('controllers.application.isLogin')
});

This follows Ember idioms more closely and I think will solve your problem.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top