-
Notifications
You must be signed in to change notification settings - Fork 144
Description
Hey there! Thanks for sharing this library, loving it! ❤️
While doing a task In work i noticed that maybe a new feature could be added to the library. When working with a lot of asynchronous calls when a page charges, it's a bit difficult to hide the spinner when the longest asynchronous call ends.
In order to perform this I implemented a Service that is a wrapper of your library which contains a Stack. Every-time that a asynchronous job start, a task is stacked (If is the first task the Spinner is shown). Once the asynchronous execution ends, it unstacks a task (If the last task is unstacked the spinner hides). I thought that this could be added to the library by doing something like this:
File: projects/ngx-spinner/src/lib/ngx-spinner.enum.ts
...
export enum SpinnerAction {
ACTION = 'action',
}
...File: projects/ngx-spinner/src/lib/ngx-spinner.service.ts
import { Injectable } from "@angular/core";
import { Observable, BehaviorSubject } from "rxjs";
import { filter } from "rxjs/operators";
import { NgxSpinner, PRIMARY_SPINNER, Spinner, SpinnerAction } from "./ngx-spinner.enum";
@Injectable({
providedIn: "root",
})
export class NgxSpinnerService {
/**
* Spinner observable
*
* @memberof NgxSpinnerService
*/
// private spinnerObservable = new ReplaySubject<NgxSpinner>(1);
public spinnerObservable = new BehaviorSubject<NgxSpinner>(null);
/**
* Spinner Stack for Async tasks
*
* @memberof NgxSpinnerService
*/
public spinnerStack = [];
/**
* Creates an instance of NgxSpinnerService.
* @memberof NgxSpinnerService
*/
constructor() {}
/**
* Get subscription of desired spinner
* @memberof NgxSpinnerService
**/
getSpinner(name: string): Observable<NgxSpinner> {
return this.spinnerObservable
.asObservable()
.pipe(filter((x: NgxSpinner) => x && x.name === name));
}
/**
* To show spinner
*
* @memberof NgxSpinnerService
*/
show(name: string = PRIMARY_SPINNER, spinner?: Spinner) {
return new Promise((resolve, _reject) => {
setTimeout(() => {
if (spinner && Object.keys(spinner).length) {
spinner["name"] = name;
this.spinnerObservable.next(
new NgxSpinner({ ...spinner, show: true })
);
resolve(true);
} else {
this.spinnerObservable.next(new NgxSpinner({ name, show: true }));
resolve(true);
}
}, 10);
});
}
/**
* To hide spinner
*
* @memberof NgxSpinnerService
*/
hide(name: string = PRIMARY_SPINNER, debounce: number = 10) {
return new Promise((resolve, _reject) => {
setTimeout(() => {
this.spinnerObservable.next(new NgxSpinner({ name, show: false }));
resolve(true);
}, debounce);
});
}
/**
* To stack a task into spinner stack
*
* @memberof NgxSpinnerService
*/
show_async(name: string = PRIMARY_SPINNER, spinner?: Spinner) {
if (!this.spinnerStack.length) {
this.show(name, spinner);
}
this.spinnerStack.push(SpinnerAction.ACTION);
}
/**
* To unstack a task of the spinner stack
*
* @memberof NgxSpinnerService
*/
hide_async(name: string = PRIMARY_SPINNER, debounce: number = 10) {
this.spinnerStack.pop();
if (!this.spinnerStack.length) {
this.hide(name, debounce);
}
}
}Simple but effective!🤓 This portion of code is just an example to undesrtand the idea, this could go in another interface different than NgxSpinnerService as well.
In this way, the spinner is always showing until all asynchronous jobs are finished, and it's not being hided all the time. It would be really good if the library could offer something similar!
Hope we can discuss about this, if you think it could be a good idea I will be more than glad on contributing with a PR!