packages/ui/src/lib/loader/loader.component.ts
The ec-loader can be plugged into various components to be triggered when they load stuff.
changeDetection | ChangeDetectionStrategy.OnPush |
selector | ec-loader |
templateUrl | ./loader.component.html |
Properties |
Methods |
constructor(host: ElementRef)
|
||||||
Injects the host element.
Parameters :
|
Private hide |
hide()
|
Hide the loader by removing .visible from the host. This method is NOT meant to be used from outside,
Returns :
void
|
Private show |
show()
|
Shows the loader by setting .visible to the host. This method is NOT meant to be used from outside,
Returns :
void
|
wait | ||||||
wait(promise: Promise
|
||||||
Tells loader to show until the given promise resolves. (includes all other promises that are waited upon) Make sure the given promise is catched (so the loader will stop loading on error)!
Parameters :
Returns :
any
|
Private stack |
Type : Collection<Promise<any>>
|
Default value : new Collection([])
|
The current stack of loading promises. |
Private timestamp |
The timestamp of the last time a promise has been added to the stack. |
Private visible |
Default value : false
|
The loader's visibility status. |
The loader can be used to indicate any kind of loading activity
<ec-loader #globalLoader class="ec-loader loader is-global"></ec-loader>
<ec-loader #localLoader class="ec-loader loader is-local"></ec-loader>
<button (click)="globalLoader()">Global Loader</button>
<button (click)="localLoader()">Local Loader</button>
The default classes can be found here.
You can use a global loader that handles every action or use multiple local loaders:
import { LoaderComponent, LoaderService } from '@ec.components/ui';
export class MyApp {
@ViewChild('globalLoader') globalLoader: LoaderComponent;
@ViewChild('localLoader') localLoader: LoaderComponent;
constructor(private loaderService: LoaderService) {
this.loaderService.use(this.globalLoader); // set global loader
}
globalLoader() { // When not passing a loader to .wait, the global loader (set by .use) is used.
this.loaderService.wait(new Promise((resolve) => setTimeout(resolve, 2000)));
}
localLoader() {
this.loaderService.wait(new Promise((resolve) => setTimeout(resolve, 2000)), this.localLoader);
// this.localLoader.wait(new Promise((resolve) => setTimeout(resolve, 2000))); // alternative way
}
}
The advantage of local loaders is that you can place them in specific places of your template to only "disable" a part of your site while loading and not the whole page. See the commented out line in localLoader for a direct way to trigger a loader without the service.
Each time .wait is called on the LoaderService, the target loader throws the given promise on a stack. When all promises on the stack have been resolved, the loader is hidden. This is better than just a boolean switch because multiple loading activies do not interfere with each other.
import { Component, ElementRef, ChangeDetectionStrategy } from '@angular/core';
import { Collection } from '@ec.components/core';
/** The ec-loader can be plugged into various components to be triggered when they load stuff.
* <example-url>https://components.entrecode.de/ui/loader?e=1</example-url>
*/
@Component({
selector: 'ec-loader',
templateUrl: './loader.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class LoaderComponent {
/** The current stack of loading promises.*/
private stack: Collection<Promise<any>> = new Collection([]);
/** The loader's visibility status. */
private visible = false;
/** The timestamp of the last time a promise has been added to the stack. */
private timestamp;
/** Injects the host element. */
constructor(private host: ElementRef) { }
/** Shows the loader by setting .visible to the host. This method is NOT meant to be used from outside, */
private show() {
this.visible = true; // show loader
this.host.nativeElement.classList.add('is-active');
}
/** Hide the loader by removing .visible from the host. This method is NOT meant to be used from outside, */
private hide() {
this.visible = false; // hide loader
this.host.nativeElement.classList.remove('is-active');
}
/** Tells loader to show until the given promise resolves. (includes all other promises that are waited upon)
* Make sure the given promise is catched (so the loader will stop loading on error)! */
wait(promise: Promise<any>) {
this.stack.add(promise); // add promise to stack
this.show();
const timestamp = Date.now();
this.timestamp = timestamp; // get timestamp
Promise.all(this.stack.items).catch(error => {
}).then(() => {
if (timestamp === this.timestamp) {
this.hide();
this.stack.removeAll();
}
});
return promise;
}
}
<ng-content></ng-content>