Computed property from a promise
-
21-12-2019 - |
Question
I have a ember-data model with a relationship(many-many). So there is a computed property depends on the relationship element. I need to return boolean value based on data of the relationship property.
isAllowed: function(){
return this.get('allowedUsers').then(function(data){
var user = this.get('currentUser');
return data.contains(user);
}.bind(this));
}.property()
In the above code, isAllowed
is the computed property and allowedUsers
is in many relation with user
model and async
is set as true
. isAllowed is getting set to the promise object rather returned boolean. I even tried to create another promise object like below but no luck.
isAllowed: function(){
return new Ember.RSVP.promise(function(resolve, reject){
this.get('allowedUsers').then(function(data){
var user = this.get('currentUser');
resolve(data.contains(user));
}.bind(this));
}.bind(this));
}.property()
How can I make sure that isAllowed is set to boolean value rather the promise object?
Solution
You should use DS.PromiseObject
:
isAllowed: Ember.computed('model.users.[]', 'session.currentUser', function() {
return DS.PromiseObject.create({
promise: this.get('session.currentUser').then((user) => {
if (!user) {
return false;
}
return this.get('model.users').isAny('id', user.get('id'));
})
});
})
OTHER TIPS
Try this:
isAllowed: function(key, value){
if (arguments.length > 1) return value; // the setter was called
this.get('allowedUsers').then(function(data){
var user = this.get('currentUser');
this.set("isAllowed", data.contains(user));
}.bind(this));
return false;
}.property()
If this were me, I would initialize with false
, then set it to resolve in the setupController
hook. For example, in your controller:
isAllowed: false, // Default with access denied
Now you can leverage your route. Routes are already juggling the model and controller, so that generally feels like the right place to resolve sideloading promises:
App.FooRoute = Ember.Route.extend({
model: function () {
//...
},
setupController: function (controller, model) {
this.setUserAccess(controller, model);
// more methods if needed...
},
setUserAccess (controller, model) {
controller.get('allowedUsers').then(function(data){
var user = controller.get('currentUser');
controller.set("isAllowed", data.contains(user));
});
}
);
I wasn't sure where allowedUsers
was coming from. You may need to tweak that.
You can do this either way, but I always feel a little icky when I override computed properties with a static property. Certainly nothing wrong with it, though.