import { Directive, Input, TemplateRef, ViewContainerRef, ComponentRef, ComponentFactoryResolver, ComponentFactory } from '@angular/core'; import { FbSpinnerComponent } from '../../common/componentDirectives/fbSpinner/fb-spinner.component'; import { IFbSpinner } from '../../common/componentDirectives/fbSpinner/fb-spinner.interface'; import * as statics from '@fb/statics'; /** * @param fbWaitFor Input: Promise | undefined. Ett promise vi väntar på ska lösas. // todo ska vi ta emot undefined? * @param type Input: IFbWaitFor.type | undefined. Typ av spinner, avser olika styling. */ @Directive({ selector: '[fbWaitFor]' }) export class FbWaitForDirective { isResolved: boolean; private spinnerRef: ComponentRef; private timeout: any; private type: IFbSpinner['type']; constructor( private readonly templateRef: TemplateRef, private readonly viewContainer: ViewContainerRef, private readonly cfResolver: ComponentFactoryResolver ) { } @Input() set fbWaitFor(waitFor: Promise) { this.clearViewContainer(); this.setup(waitFor); } @Input() set fbWaitForType(type: IFbSpinner['type']) { this.type = type; } private clearViewContainer(): void { clearTimeout(this.timeout); this.viewContainer.clear(); this.isResolved = false; } private waitForPromise(promise: Promise): void { promise.then(() => { this.onPromiseResolved(); }).catch(() => { this.spinnerRef.instance.error = true; }); } private onPromiseResolved(): void { this.viewContainer.clear(); this.viewContainer.createEmbeddedView(this.templateRef); this.isResolved = true; } private setup(waitFor: Promise): void { const delayTime: number = 100; this.timeout = setTimeout(() => { if (!this.isResolved) { this.createSpinner(); } if (statics.isDefined(waitFor)) { if (!waitFor.then) { throw new Error(`fbWaitFor expects a promise but got a/an ${typeof waitFor}. Did you forget to send in the ${typeof waitFor}´s promise?`); } this.waitForPromise(waitFor); } }, delayTime); } private createSpinner(): void { const spinnerFactory: ComponentFactory = this.cfResolver.resolveComponentFactory(FbSpinnerComponent); this.spinnerRef = this.viewContainer.createComponent(spinnerFactory, null, null); if (statics.isDefined(this.type)) { (this.spinnerRef.instance as FbSpinnerComponent).type = this.type; } } }