Is there a good way to render the result of a promise in a handlebars template?
For example, I have the following model:
App.TopicItem = DS.Model.extend({
topic: DS.belongsTo('topic'),
paddedPosition: function() {
return this.get('topic.course.lessons').
then(function(lessons) {
return lessons.indexOf(topicItem);
}).
then(function(index){
var position = index;
if (position < 0) {
return;
}
position = position + 1;
return (position < 10 ? $.rjust(position, 2, '0') : position.toString());
});
}.property('topic.course.lessons')
});
And I would like to render the value of the position in the handlebars template like this:
{{topicItem.paddedPosition}}
Is there a good way to accomplish this?
You could have the property lazily set itself, something like:
App.TopicItem = DS.Model.extend({
topic: DS.belongsTo('topic'),
paddedPosition: function(key, value) {
if (arguments.length > 1) {
// > 1 args = this is a `set`
return value;
} else {
// otherwise this is a `get`
var _this = this;
value = null;
this.get('topic.course.lessons').
then(function(lessons) {
// do stuff based on result
var padded = ...;
// when the promise is resolved, set this property with the value
_this.set("paddedPosition", padded);
// if the promise resolves immediately, set `value` so we return
// the calculated value and not null
value = padded;
});
// returns null if the promise doesn't resolve immediately, or
// the calculated value if it's ready
return value;
}
}.property('topic.course.lessons')
});
When it's first accessed it'll kick-off the calculation, likewise any time the lessons change, then it'll set itself as the result of the calculation once it's done.
This works because a computed property is called both on get and set, you can differentiate between the two by the number of arguments - 1 for get, more than 1 for set (it used to be 2, now you get 3 so the best way to detect is > 1). More on that in the docs.
Whatever's returned from a computed property (either in get or set) is cached until its dependent properties change - in this case topic.course.lessons
.
In the above example, when the first get
comes in we kick off the calculation and return null
. This is now cached as the value of the property, if anything else calls this property before the promise has resolved then it'll return null
.
Once the promise resolves, we call set
on the same property with the calculated value. This we just return in the setter and it's now cached as the value of the property.
Until the dependent properties change (topic.course.lessons
), or a new value is set
then the cached value is returned from the property.
That seems like an unexpected behaviour. There's a bug filled for that problem: https://github.com/emberjs/ember.js/issues/11046
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With