ember.jsember-router

Ember application.hbs template child components not reloading


I am trying to implement a nav bar that displays either Sign in or Sign out depending on a boolean value in an Ember Service that I have injected into the application route (defined in routes/application.js).

I also read this and it reaffirms my choice of the service approach of handling state.

Now the question and problem is that the child components are not updating when I redirect from one route to another. If the link says Sign in, when I successfully authenticate and sign in, the link will still say Sign in. It's only when I refresh the page does the link text change to Sign out. The Sign out link behavior is the same.

Code in application.hbs:

  {{nav-bar isAuthenticated=isAuthenticated}} ==> seems like only loaded once
  {{outlet}}

Code for the sign-in and sign-out links in nav-bar.hbs:

  {{log isAuthenticated }} ==> only prints upon page load, doesn't print on route changes
  {{#if isAuthenticated}}
    <ul class="nav navbar-nav navbar-right">
      {{#link-to 'logout' tagName="li" class="nav-item"}}<a class="nav-link" href="">Logout</a>{{/link-to}}
    </ul>
  {{else}}
    <ul class="nav navbar-nav navbar-right">
      {{#link-to 'login' tagName="li" class="nav-item"}}<a class="nav-link" href="">Login</a>{{/link-to}}
    </ul>
  {{/if}}

My log-in action:

  this.transitionTo('dashboard');

Problem is that it transitions without updating the nav bar. Why is that? What can I do to run around this problem?

Update regarding comments and first answer:

What if I don't have an application controller? I have this so far in my application Route but it's still not updating even though I'm passing the data down to the nav bar component:

  simpleAuthManager: Ember.inject.service(),
  isAuthenticated: Ember.computed('simpleAuthManager', 'simpleAuthManager.user', function() {
    console.log(this.get('simpleAuthManager.user'));
    return this.get('simpleAuthManager').isAuthenticated();
  }),

  setupController(controller, model) {
    this._super(controller, model);
    controller.set('isAuthenticated', this.get('isAuthenticated'));
  }

Solution

  • A computed property is required to recompute the state every time isAuthenticated changes.

    As I understand, you have a nav-bar child component present in your application template and have a service that manages the current logged-in/logged-out state of your application. Computed properties along with service injection can help you here.

    Set up a computed property that watches your isAuthenticated variable from your service in your application controller (make a controller if you haven't). Pass the isAuthenticated as a parameter to your nav-bar component. In the nav-bar component inject the service as well, and have it set the authenticated state in an action every time a log-in/log-out link is clicked.

    This way each time someone logs in or out your service is updated and as a consequence so is your isAuthenticated computed property in your application controller.

    You can read up on Ember's computed properties here.