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