Set property on application controller from sign-in action

Hopefully a general question. I am building a greenfield 4.x ember app. I’m using ember-simple-auth. When a user signs in, I’d like to set a property on the application controller so that a nav bar component in the application template reflects the current user’s name. Old google searches talked about a controllerFor in controller but that appears to be deprecated (though still availble in route, I think).

// app/templates/application.hbs
<NavBar @profile={{ this.currentProfile }} />
{{outlet}}
// app/controllers/sign-in.js
export default class SignInController extends Controller {
  @action
  async authenticate(event) {
    event.preventDefault();
    await this.session.authenticate('authenticator:jwt', { user: { email: this.email, password: this.password } }).then(() => {
      // this doesn't work, but am I on the right track or is this not the ember way of doing things?
      this.controllerFor('application').set('currentProfile', this.store.find('profile', 'me'));
      this.router.transitionTo('welcome');
    });
  }
}

The easiest way (and I think most modern) to do cross-area communication in your app is to use services.

So, maybe you’d have a service, called “current user”

ember g service current-user

and define a profile property on it:

import Service from '@ember/service';
import { tracked } from '@glimmer/tracking';

export default class CurrentUserService extends Service {
  @tracked profile;
}

your app/controllers/application.js controller, you’d inject it

import Controller from '@ember/controller';
import { service } from '@ember/service';

export default class ApplicationController extends Controller {
  @service currentUser;

  get currentProfile() {
    return this.currentUser.profile;
  }
}

and then in your sign-in controller, you could also inject the controller and set the profile property:

export default class SignInController extends Controller {
  @service currentUser;

  @action
  async authenticate(event) {
    event.preventDefault();
    await this.session.authenticate('authenticator:jwt', { user: { email: this.email, password: this.password } })

    this.currentUser.profile = await this.store.find('profile', 'me');
    this.router.transitionTo('welcome');
  }
}
2 Likes

Thank you for the quick response. That worked perfectly.

I had tried something like this before, for what it’s worth, but I had the <NavBar component use the service directly and the service directly queried the store (e.g. this.store.findRecord('profile', 'me') which resulted in a never-ending series of queries. This seems much cleaner.

2 Likes