undefined
undefined

Reputation: 3632

Show loading bar for every http request angular2

I am moving my app from angularjs to angular2. I was using Angular Loading Bar which is

An automatic loading bar using angular interceptors. It works automatically, so simply include it as a dependency and it will automatically display the progress of your $http requests.

More info

I am trying to find similar plugin in angular2. I came across a few like ng2-slim-loading-bar but here I have to manually manage the progress. For every http request, I have to manually start the progress bar and then finish it.

So, are there any existing plugin available which can do exactly what Angular Loading Bar does in angularjs. Or how can I modify any existing plugin to behave like this.

Upvotes: 5

Views: 18167

Answers (3)

Reza
Reza

Reputation: 19933

check @ngx-loading-bar which automatically will add progress bar for Http calls and routings

https://github.com/aitboudad/ngx-loading-bar

Upvotes: 1

Ondra Žižka
Ondra Žižka

Reputation: 46904

Here is what I did in our project (Red Hat Automated Migration Toolkit):

  • In our HTTP service wrapper (handling OAuth), we fire an event,
  • which is then caught by our LoadingIndicatorService.
  • LoadingIndicatorService
    • wraps the SlimLoaderBarService,
    • and keeps track of how many HTTP requests there are in progress.
    • Then it counts the percent and puts it to a scale of 20 to 90 %.
    • When all HTTP requests are done, it stays at 90 % for about a second, and then complete() is called.

If you have multiple requests for each navigation step, this looks quite naturally and provides a good UX. If you typically only have 1 request, then you might want to either adjust the CSS based animation (make it longer) or use start() afterall.

Here are some key code parts:

@Injectable()
export class LoadingIndicatorService {

    constructor(
        private _slimBarService: SlimLoadingBarService,
        private _eventBusService: EventBusService,
    ) {
        // Register the LoadingSomething event listeners.
        this._eventBusService.onEvent
            .filter(event => event.isTypeOf(LoadingSomethingStartedEvent))
            .subscribe((event: LoadingSomethingStartedEvent) => this.loadingStarted() )
        this._eventBusService.onEvent
            .filter(event => event.isTypeOf(LoadingSomethingFinishedEvent))
            .subscribe((event: LoadingSomethingFinishedEvent) => this.loadingFinished() )
    }

    public getSlimService(){
        return this._slimBarService;
    }


    private counter: number = 0;
    private max: number = void 0;

    private reset() {
        this.counter = 0;
        this.max = void 0;
    }

    public loadingStarted(){
        this.counter++;
        this.max = this.counter;
        this.updateProgress();
    }

    public loadingFinished(){
        this.counter--;
        this.updateProgress();
    }

    private updateProgress() {
        if (this.counter == 0) {
            this._slimBarService.height = "2px";
            this._slimBarService.visible = true;
            this._slimBarService.progress = 95;
            this.max = void 0;
            Observable.timer(700).subscribe(() => {
                this._slimBarService.complete();
            });
        }
        else {
            // max - counter = finished.
            // If the things to load are added after something loaded, the progress would go back.
            // But let's rely on that loading will start fast at the beginning.
            // Start at 20, jump to 90.
            let percent = 20 + 70 * (1 - (this.max - this.counter) / this.max);
            this._slimBarService.height = "3px";
            this._slimBarService.color = "#39a5dc";
            this._slimBarService.visible = true;
            this._slimBarService.progress = percent;
        }
    }

}


    let responseObservable2 = responseObservable.do(
        () => console.log("Request SUCCEEDED"),
        () => console.log("Request FAILED"),
        () => {
            console.log("Request FINISHED");
            if (this._eventBus) {
                console.log("Request FINISHED, firing");
                this._eventBus.fireEvent(new LoadingSomethingFinishedEvent(responseObservable))
            }
        }
    );

HTTP service wrapper:

@Injectable()
export class WindupHttpService extends Http {

    private configureRequest(method: RequestMethod, f: Function, url: string | Request, options: RequestOptionsArgs = {}, body?: any): Observable<Response> {
        let responseObservable: Observable<Response> = ...

    ...

    console.log("Load STARTED");
    if (this._eventBus)
        console.log("Load STARTED, firing");
    this._eventBus.fireEvent(new LoadingSomethingStartedEvent(responseObservable));

    return responseObservable2;
}

For the complete code, search github.com for project Windup.

Upvotes: 1

Radouane ROUFID
Radouane ROUFID

Reputation: 10843

You can use ngx-progressbar. It can automatically show the progress bar while a HTTP request is running.

All you have to do is :

1- Import and provide NgProgressCustomBrowserXhr

import { NgProgressCustomBrowserXhr } from 'ngx-progressbar';

@NgModule({
 providers: [
   // ...
   { provide: BrowserXhr, useClass: NgProgressCustomBrowserXhr } ,
 ],
 imports: [
   // ...
   NgProgressModule
 ]
})

2- Use it like below in your template.

<ng-progress></ng-progress>

The progress will start and complete automatically with your HTTP requests. no need to use NgProgressService to call start()/done() manually.

Upvotes: 14

Related Questions