Reputation: 8203
I have been struggling with this for the past two days. I can't find a way to refresh a controller property in Ember - in other words, make the handlebars template look up for the controller property again, other than caching the old value. The problem has to do with sessionStorage. Here's the code:
<script type="text/x-handlebars" id="start">
{{log isLoggedIn}}
{{#if isLoggedIn}}
<p>Welcome, <strong>{{controllers.application.name}}</strong>!<br/>
Your user role is: <strong>{{controllers.application.role}}</strong></p>
{{else}}
<p>Unfortunately, you're not logged in so you cannot access this content.</p>
{{/if}}
</script>
The application handlebars template has a link for log in.
Here's a part of my app.js:
App.ApplicationController = Ember.ObjectController.extend({
session: false,
hasSession: function() {
var session = window.sessionStorage.getItem("session");
if (session) {
this.set("session", true);
return session.length === 16;
}
return false;
}.property("session"),
App.StartController = Ember.ObjectController.extend({
needs: ["application"],
isLoggedIn: function() {
return this.get("controllers.application.hasSession");
}.property("controllers.application.hasSession")
});
App.LoginController = Ember.ObjectController.extend({
username: "deus",
password: "ha", //TODO: replace with null
actions: {
login: function() {
logIn(this);
}
}
});
function logIn(self) {
$.ajax({
dataType: "json",
url: "userValidation.json",
async: false,
success: function(data) {
if (data.status.code === 200) {
window.sessionStorage.setItem("session", data.users.session);
window.sessionStorage.setItem("permissions", data.users.permissions);
window.sessionStorage.setItem("username", data.users.username);
window.sessionStorage.setItem("name", data.users.name);
} else {
alert("Unable to log in! Status code is " + data.status.code.toString());
}
}
}).done(function() {
//TODO: Move logic here?
});
}
I've tried all I can think of. I see in my chrome developer's console that the session is set properly. However, when I navigate to the start
page, I get that "unfortunately" message. My console log says that session is false.
If I try this:
App.ApplicationController = Ember.ObjectController.extend({
hasSession: function() {
return getLoggedIn();
}
});
function getLoggedIn() {
var session = window.sessionStorage.getItem("session");
if (session) {
return session.length === 16;
}
return false;
}
I still have the same (or rather similar) problem - navigating to the start
page still shows the message as if the user is not logged in, even though sessionStorage has all the stuff. But when I refresh the page manually, it gives me the proper "Welcome" message.
How can I solve this problem? Basically, I need the controller to "understand" that the session has changed, and realize that the user has logged in - or, in other words, I need to refresh the controller's property (without reloading the page).
Upvotes: 1
Views: 2472
Reputation: 47367
Ember doesn't have any built in functionality for watching the session storage, but it really isn't necessary here. You can just do it in the resolved ajax call (something like this).
App.ApplicationController = Ember.ObjectController.extend({
session: '',
hasSession: function() {
return this.get('session.length') === 16;
}.property("session"),
App.StartController = Ember.ObjectController.extend({
needs: ["application"],
isLoggedIn: Em.computed.alias("controllers.application.hasSession")
});
App.LoginController = Ember.ObjectController.extend({
needs: ["application"],
application: Em.computed.alias("controllers.application"),
username: "deus",
password: "ha", //TODO: replace with null
actions: {
login: function() {
var self = this;
logIn(this).done(function(result){
var session = result.users.session; // or whatever this is
self.set('application.session', session);
});
}
}
});
function logIn(self) {
return $.ajax({
dataType: "json",
url: "userValidation.json",
async: false,
success: function(data) {
if (data.status.code === 200) {
window.sessionStorage.setItem("session", data.users.session);
window.sessionStorage.setItem("permissions", data.users.permissions);
window.sessionStorage.setItem("username", data.users.username);
window.sessionStorage.setItem("name", data.users.name);
} else {
alert("Unable to log in! Status code is " + data.status.code.toString());
}
}
})
}
Ember's computed properties are cached by default and are lazily loaded. This means that the only way a property is recalculated is if one of the dependent properties has changed. In the example below, if you were to change bar, foo would then be marked dirty, and then be recalculated (if being watched by someone);
bar:'asdf',
foo: function(){
return this.get('bar');
}.property('bar')
In this example it would also only get recalculated if bar changed. Unfortunately if baz changed foo wouldn't be recalculated.
bar:'asdf',
baz:'fdas',
foo: function(){
return this.get('bar') + this.get('baz');
}.property('bar')
Volatile computed properties will be recalculated every time they are requested.
bar:1,
foo: function(){
this.incrementProperty('bar');
return this.get('bar');
}.property().volatile(),
blah: function(){
this.get('foo');
this.get('foo');
this.get('foo');
}
Example: http://emberjs.jsbin.com/donalabu/1/edit
Upvotes: 4