Thursday, March 17, 2016

Aurelia custom element async life cycle event

I saw a really good conversation in the Aurelia/framework Github issue queue that I wanted to save for later.  https://github.com/aurelia/framework/issues/367#issuecomment-198104416

From Rob Eisenberg:

We can't provide this (async promise life-cycle events) across all components. It would be a disaster for performance and would no longer map in any way to web components. 
If you don't care about web components, you can use the new CompositionTransaction: http://aurelia.io/docs.html#/aurelia/templating/1.0.0-beta.1.1.2/doc/api/class/CompositionTransaction 
Simply have that injected into your component constructor and then call enlist() this will return you a CompositionTransactionNotifier: http://aurelia.io/docs.html#/aurelia/templating/1.0.0-beta.1.1.2/doc/api/interface/CompositionTransactionNotifier 
You can call done on that when your async operation is complete. The global composition will wait to attach until after you are done.

How do I wait for async data for an Aurelia custom element?


import { HttpClient } from 'aurelia-fetch-client';
import { CompositionTransaction } from 'aurelia-framework';
export class YearToDateGauge {
static inject = [HttpClient, CompositionTransaction];
constructor(http, compositionTransaction) {
this.http = http;
this.compositionTransaction = compositionTransaction;
// https://github.com/aurelia/framework/issues/367
this.compositionTransaction = compositionTransaction;
this.compositionTransactionNotifier = null;
}
// From Rob Eisenberg:
// If you ever wanted to use view caching, using created() would not work because when a view is
// cached its created callback is only called once on the initial creation, not when it is reused.
// However, bind, attached, detached and unbind are always called. Also, in many cases, the async
// composition operation is dependent on some data, which would not usually be available until the
// bind phase. For the specific example above, it might not matter.
bind() {
this.compositionTransactionNotifier = this.compositionTransaction.enlist();
// return a promise that resolves when the data is retrieved
this.http.fetch('/books/')
.then(data => {
this.books = data; // store locally
// done loading data, allow the attached() hook to fire
this.compositionTransactionNotifier.done();
return data;
});
}
// fires only after the promise from `bind()` either resolves or rejects
attached() {
// update the DOM here, e.g. draw a chart, etc
this.numBooks = this.books.length; // the user is guaranteed that this.books will be availaible
}
}

No comments:

Post a Comment