Menu iconMenu

Displaying Asynchronous Data in Templates

In Ember, a situation we commonly run into is needing to display asynchronous data in a template. A lot of the time this works really well, for example: Ember has some smarts around displaying related models within templates.

The below example shows a simple library application displaying authors and their published books:

1

As you can see, despite the fact that getting the books is an asynchronous traversal of a relationship, the template renders correctly once the books have been fetched.

This is all well and good, but when you want to display some asynchronous data that isn’t just properties on a related model it gets more difficult.

For example, what if we wanted to asterisk authors that had published in the last two years? This requires us to get the related books and run a little logic. This seems like a useful function to have on our model so we can reuse it throughout our application.

However, now we can no longer use that value directly in the template – in fact, it requires some restructuring of our application. We could possibly pass in the resolved promise as part of our route model, however this will be clunky as we have a list of authors. Another approach is to create a separate component that is responsible for displaying the author. This component could call hasPublishedRecently  and set a property on the component once the promise resolves.

 

This works, but requires us to add a new component as well as a chunk of extra code just to display the resolved promise value.

Using DS Promises

Ember does provide another way to do this. Rather than a function on the model we can use a computed property and if it returns a special type of object it can be used directly in the template. Ember Data provides these two classes:

They use the PromiseProxyMixin to give the Ember objects extra properties and methods that the templates can work with.

To demonstrate, we can adapt the previous example to use a computed property and return a PromiseObject  instance instead of a plain promise.

Now we can use it directly in our template:

2

Notice we now need to use the content  property of the object to display it in the template? If you want to ensure that the promise has resolved you can also use the properties isPending  or isSettled . See the PromiseProxyMixin for others.

For example, if we had a promise telling us if the book was available or on loan, we could wrap it in an unless isPending  block so nothing will show until the result was known:

Drawbacks of DS Promises

Forgetting to use content or isPending properties

One drawback of this approach is that you now need awareness of whether you are dealing with a promise or a value in your templates. One convention we’ve used in our projects is giving the computed properties resolving to promises a Promise  suffix.

 

This adds a few more keystrokes but does make it much clearer in templates when dealing with these properties.

Boilerplate

This approach still requires some boilerplate code. It needs the promise to be wrapped in a DS.PromiseObject.create()  call and accessing the content property in the template. It may be possible to remove this with a helper that can take a regular promise and abstract away the details of PromiseObject  and optionally wrap the template code within an unless isPending  block.

Although we haven’t tried it, this library also looks promising and solves the same problem https://github.com/fivetanley/ember-promise-helpers.

References

To see a working example of this code, you can check out the repository at https://github.com/mediasuitenz/promise-template-blog-post.

A Day in the Life of an Ember Concurrency Task…

Media Suite's itinerant American developer explores one of the nuances of ember-concurrency.
Patrick Posted by Patrick on 19 October, 2016

Ember Blueprints: why they’re awesome

Brit-turned-Queenstowner and keen coder Jonathan on why he's a fan of Ember Blueprints. Note: This is part one of a. . . (yet-to-be-decided-how-many-parts) series on this subject.
Jonathan H Posted by Jonathan H on 11 August, 2017

Managing Relations in Ember Data with JSON API

From his villa in beautiful Bali, our nomad developer Patrick weighs in on this technical issue. He even provides demo-code.
Patrick Posted by Patrick on 18 August, 2017
Comments Comments
Add comment

Leave a Reply

Your email address will not be published.