I have created a top navbar in my ember.js application and converted it to a component so that I can have a simple "Welcome {{currentUser.fullName}}" introduction once a user signs in. There are some other reasons why the navbar is going to be a component, but for now this is what I am trying to get working correctly. We are also using ember-simple-auth addon and I am using the session.isAuthenticated
value to make this happen.
Of course I have a 'login' route, that when the user signs in, they are transitioned to the 'index'. For some reason it doesn't seem like the session.isAuthenticated
value is caught right away during the transition to the 'index'. I don't know why this is, but that is another issue.
Anyway, I am using a lot of components in this application and most of those components get their values from the sessions and querying the store independently of the routes so that I can use these components on multiple routes. The navbar is no exception. Right now I have the following working code:
export default Ember.Component.extend({
layout,
session: Ember.inject.service(),
currentUser: Ember.inject.service(),
isAuthenticated: Ember.observer('session.isAuthenticated', function() {
this.didReceiveAttrs();
}),
currentUserFullName: null,
user: null,
tagName: 'navbar-main',
className: ['navbar', 'main'],
didReceiveAttrs() {
this._super(...arguments);
if (this.get('session.isAuthenticated')) {
this._setCurrentUser();
}
},
_setCurrentUser() {
this.get('currentUser').load().then(user => this.set('user', user));
},
onGetCurrentUser: Ember.observer('user', function() {
this.getUser();
}),
getUser: function() {
var user = this.get('user');
if(user) {
this.set('user', user);
this.set('currentUserFullName', user.get('fullName'));
} else {
user = this.get('store').findRecord('user', 'me');
this.set('user', user);
this.set('currentUserFullName', user.get('fullName'));
}
}
});
Everything I am reading suggests to just use didReceiveAttrs()
instead of an observer. Also, it says that computed properties are usually what you want to use over observers. However I can't seem to get anything to work without the following:
isAuthenticated: Ember.observer('session.isAuthenticated', function() {
this.didReceiveAttrs();
}),
If I try to convert it to a computed property it doesn't seem to do anything on a property change unless I refresh the page after it has already transitioned to the 'index' route. If I try to use just the didReceiveAttrs()
method with this.get('session.isAuthenticated') logic, a page refresh is still needed.
So what am I not understanding about how to use Ember.computed
and didReceiveAttrs()
? Can someone give me an example? Or show me a more efficient way to do what I am trying to accomplish?
UPDATED CODE:
// app/pods/components/navbar-main/component.js
import Ember from 'ember';
import layout from './template';
export default Ember.Component.extend({
layout,
session: Ember.inject.service(),
currentUser: Ember.inject.service(),
user: null,
isAuthenticated: Ember.observer('session.isAuthenticated', function() {
this.get('currentUser').load().then(user => this.set('user', user));
}),
currentUserFullName: Ember.computed.alias('user.fullName'),
tagName: 'navbar-main',
className: ['navbar', 'main'],
didReceiveAttrs() {
this._super(...arguments);
if(this.get('session.isAuthenticated')) {
this.isAuthenticated();
}
}
});
<!-- app/pods/components/navbar-main/template.hbs -->
{{#if session.isAuthenticated}}
<div class="ui black user login label">
<div class="ui grid">
<div class="twelve wide column">
<div class="detailed">{{currentUserFullName}}<br>Welcome</div>
</div>
<div class="four wide column" style="padding-top: 12px; margin-top: 0;">
<img class="ui top aligned small avatar image" src="http://semantic-ui.com/images/avatar/small/christian.jpg">
<!--<img class="ui top aligned tiny avatar image" src="{{currentUser.avatar}}">-->
</div>
</div>
</div>
{{/if}}
UPDATE 2 (Final code with help from @AdamCooper and @kumkanillam):
export default Ember.Component.extend({
layout,
session: Ember.inject.service(),
currentUser: Ember.inject.service(),
user: null,
isAuthenticated: Ember.on('init', Ember.observer('session.isAuthenticated', function() {
this.get('currentUser').load().then(user => this.set('user', user));
})),
currentUserFullName: Ember.computed.alias('user.fullName'),
tagName: 'navbar-main',
className: ['navbar', 'main']
});
So this is the least amount of code, still using observer and computed methods, but not using the component lifecycle. So I guess it is still necessary to use observers sometimes is what I have come up with.
This is what I ended up with that worked for my situation:
export default Ember.Component.extend({
layout,
session: Ember.inject.service(),
currentUser: Ember.inject.service(),
user: null,
isAuthenticated: Ember.on('init', Ember.observer('session.isAuthenticated', function() {
this.get('currentUser').load().then(user => this.set('user', user));
})),
currentUserFullName: Ember.computed.alias('user.fullName'),
tagName: 'navbar-main',
className: ['navbar', 'main']
});
This is using a combination of Ember Freak's and Adam Cooper's answers to this question.