One of Aurelia’s strengths is the way that it provides a set of well-designed building blocks that you can use in a variety of different ways. One of these building blocks is the HttpClient
, a wrapper for the browsers Fetch API which is a modern replacement for the old XMLHttpRequest
object.
This morning I was looking for a way to show loading progress in a simple and consistent way across a new application I’m building. The goal was to give the user some kind of visual feedback any time I was making an Http request. Looking around I found the nprogress library, which does a great job of showing a slim progress bar in a way similar to apps like Youtube.
Hooking this up was simple:
npm install nprogress --save
Import the styles at the top of my app.ts
:
import 'nprogress/nprogress.css';
Then, in my application, I set the HttpClient
up with an interceptor to automatically add some required headers to each request. Interceptors are one of those powerful features that buy you a great amount of flexibility when using the HttpClient
. So, I decided to modify my interceptor slightly to also report progress via nprogress
.
First I needed to import the module:
import * as nprogress from 'nprogress';
From there it was a simple matter of modifying my intercepter to report progress on the start and end of each request:
get interceptor(){
return {
request(request) {
nprogress.start() //report loading started
request.headers.append('appId', this.state.appId);
return request;
},
response(response) {
nprogress.done() //report loading finished
return response;
}
};
}
This took me only a few minutes to wire up, but is working nicely. It got me thinking, there are probably many other novel use cases for the various features of Aurelia’s Fetch client and HttpClient, interceptors, and more. I’d be interested to see examples of what other’s are doing.
Edit:
As @huochunpeng quite rightly points out, there is another feature of the HttpClient
which makes this even simpler. The HttpClient
has an isRequesting
property to maintain the state of when requests are being made. So, a more elegant way to implement this logic is to create a custom element, like the loading indicator from the app contacts sample https://github.com/aurelia/app-contacts/blob/master/src/resources/elements/loading-indicator.js.
import * as nprogress from 'nprogress';
import {bindable, noView} from 'aurelia-framework';
@noView()
export class LoadingIndicator {
@bindable loading = false;
loadingChanged(newValue){
if(newValue){
nprogress.start();
}else{
nprogress.done();
}
}
}
This element is then included in the top of your page, and can be used to trigger nprogress
as follows:
<loading-indicator loading.bind="router.isNavigating || http.isRequesting"></loading-indicator>