Here\'s the problem. I have three states of almost all the pages in my app. 1. Loading (where I want to show spinner within the page and for that I have created a component alre
Advertisement: This is a response in Angular (I suppose can be inspiration for Ionic)
You can create an operator, see this SO
Well, change the operator to send 1 when start loading, -1 if finalize without no data and 0 if finalize with data:
The operator:
export const prepare = <T>(callback: () => void) => {
return (source: Observable<T>): Observable<T> =>
defer(() => {
callback();
return source;
});
};
export const indicate = <T>(indicator: Subject<any>) => {
let alive = true;
let noData=false;
return (source: Observable<T>): Observable<T> =>
source.pipe(
prepare(() =>
timer(500)
.pipe(
takeWhile(() => alive),
take(1)
)
.subscribe(() => {
indicator.next(1);
})
),
tap(res=>{
noData=(!res || (Array.isArray(res) && res.length<=0))
}),
finalize(() => {
alive = false;
indicator.next(noData?-1:0);
})
);
};
export const toClass = <T>(ClassType: { new(): T }) => (
source: Observable<T>
) => source.pipe(map(val => Object.assign(new ClassType(), val)));
the loading component:
@Component({
selector: 'app-loading',
template:`
<div *ngIf="dataService.loading$ | async as response">
<div class="modal" (click)="dataService.loading$.next(0)">
<div class="modal-content">
<p *ngIf="response==1">Loading...</p>
<p *ngIf="response==-1">Empty</p>
</div>
</div>
</div>
`,
styleUrls: [ './loading.component.css' ]
})
export class LoadingComponent {
constructor(public dataService:DataService){}
}
See how close the modal using dataService.loading$.next(0)
and how I declared as public my dataService in the constructor
I make a simple example of use
<button (click)="loadData()">load</button>
<div>
{{data}}
</div>
<app-loading></app-loading>
And a simple service that simulate a call, return random null or the date time
export class DataService {
loading$ = new Subject<any>()
getData():Observable<any>
{
const observable=of(Math.random()<.5?
'New Data at '+new Date():
null
).pipe(delay(1000))
return observable.pipe(
indicate(this.loading$))
}
}
You can see the stackblitz, You see the "loading", then, some times you'll see that is empty, and another time the "loading" close.