|
|
@ -1,17 +1,16 @@ |
|
|
import { |
|
|
import { |
|
|
ComponentFactoryResolver, |
|
|
|
|
|
ComponentRef, |
|
|
ComponentRef, |
|
|
Directive, |
|
|
Directive, |
|
|
ElementRef, |
|
|
ElementRef, |
|
|
EmbeddedViewRef, |
|
|
EmbeddedViewRef, |
|
|
HostBinding, |
|
|
|
|
|
Injector, |
|
|
Injector, |
|
|
Input, |
|
|
|
|
|
OnDestroy, |
|
|
OnDestroy, |
|
|
OnInit, |
|
|
OnInit, |
|
|
Renderer2, |
|
|
Renderer2, |
|
|
|
|
|
effect, |
|
|
inject, |
|
|
inject, |
|
|
input |
|
|
input, |
|
|
|
|
|
ViewContainerRef |
|
|
} from '@angular/core'; |
|
|
} from '@angular/core'; |
|
|
import { Subscription, timer } from 'rxjs'; |
|
|
import { Subscription, timer } from 'rxjs'; |
|
|
import { take } from 'rxjs/operators'; |
|
|
import { take } from 'rxjs/operators'; |
|
|
@ -19,29 +18,38 @@ import { LoadingComponent } from '../components'; |
|
|
|
|
|
|
|
|
@Directive({ |
|
|
@Directive({ |
|
|
selector: '[abpLoading]', |
|
|
selector: '[abpLoading]', |
|
|
|
|
|
host: { |
|
|
|
|
|
'[style.position]': '"relative"' |
|
|
|
|
|
} |
|
|
}) |
|
|
}) |
|
|
export class LoadingDirective implements OnInit, OnDestroy { |
|
|
export class LoadingDirective implements OnInit, OnDestroy { |
|
|
private elRef = inject<ElementRef<HTMLElement>>(ElementRef); |
|
|
private elRef = inject<ElementRef<HTMLElement>>(ElementRef); |
|
|
private cdRes = inject(ComponentFactoryResolver); |
|
|
|
|
|
private injector = inject(Injector); |
|
|
private injector = inject(Injector); |
|
|
private renderer = inject(Renderer2); |
|
|
private renderer = inject(Renderer2); |
|
|
|
|
|
private viewContainerRef = inject(ViewContainerRef); |
|
|
|
|
|
|
|
|
private _loading!: boolean; |
|
|
readonly loading = input(false, { alias: 'abpLoading' }); |
|
|
|
|
|
readonly targetElementInput = input<HTMLElement | undefined>(undefined, { alias: 'abpLoadingTargetElement' }); |
|
|
|
|
|
readonly delay = input(0, { alias: 'abpLoadingDelay' }); |
|
|
|
|
|
|
|
|
@HostBinding('style.position') |
|
|
private targetElement: HTMLElement | undefined; |
|
|
position = 'relative'; |
|
|
|
|
|
|
|
|
|
|
|
@Input('abpLoading') |
|
|
componentRef: ComponentRef<LoadingComponent> | null = null; |
|
|
get loading(): boolean { |
|
|
rootNode: HTMLDivElement | null = null; |
|
|
return this._loading; |
|
|
timerSubscription: Subscription | null = null; |
|
|
|
|
|
|
|
|
|
|
|
constructor() { |
|
|
|
|
|
effect(() => { |
|
|
|
|
|
const newValue = this.loading(); |
|
|
|
|
|
this.handleLoadingChange(newValue); |
|
|
|
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
set loading(newValue: boolean) { |
|
|
private handleLoadingChange(newValue: boolean) { |
|
|
setTimeout(() => { |
|
|
setTimeout(() => { |
|
|
if (!newValue && this.timerSubscription) { |
|
|
if (!newValue && this.timerSubscription) { |
|
|
this.timerSubscription.unsubscribe(); |
|
|
this.timerSubscription.unsubscribe(); |
|
|
this.timerSubscription = null; |
|
|
this.timerSubscription = null; |
|
|
this._loading = newValue; |
|
|
|
|
|
|
|
|
|
|
|
if (this.rootNode) { |
|
|
if (this.rootNode) { |
|
|
this.renderer.removeChild(this.rootNode.parentElement, this.rootNode); |
|
|
this.renderer.removeChild(this.rootNode.parentElement, this.rootNode); |
|
|
@ -54,9 +62,9 @@ export class LoadingDirective implements OnInit, OnDestroy { |
|
|
.pipe(take(1)) |
|
|
.pipe(take(1)) |
|
|
.subscribe(() => { |
|
|
.subscribe(() => { |
|
|
if (!this.componentRef) { |
|
|
if (!this.componentRef) { |
|
|
this.componentRef = this.cdRes |
|
|
this.componentRef = this.viewContainerRef.createComponent(LoadingComponent, { |
|
|
.resolveComponentFactory(LoadingComponent) |
|
|
injector: this.injector |
|
|
.create(this.injector); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (newValue && !this.rootNode) { |
|
|
if (newValue && !this.rootNode) { |
|
|
@ -67,22 +75,13 @@ export class LoadingDirective implements OnInit, OnDestroy { |
|
|
this.rootNode = null; |
|
|
this.rootNode = null; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
this._loading = newValue; |
|
|
|
|
|
this.timerSubscription = null; |
|
|
this.timerSubscription = null; |
|
|
}); |
|
|
}); |
|
|
}, 0); |
|
|
}, 0); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Input('abpLoadingTargetElement') |
|
|
|
|
|
targetElement: HTMLElement | undefined; |
|
|
|
|
|
|
|
|
|
|
|
readonly delay = input(0, { alias: "abpLoadingDelay" }); |
|
|
|
|
|
|
|
|
|
|
|
componentRef!: ComponentRef<LoadingComponent>; |
|
|
|
|
|
rootNode: HTMLDivElement | null = null; |
|
|
|
|
|
timerSubscription: Subscription | null = null; |
|
|
|
|
|
|
|
|
|
|
|
ngOnInit() { |
|
|
ngOnInit() { |
|
|
|
|
|
this.targetElement = this.targetElementInput(); |
|
|
if (!this.targetElement) { |
|
|
if (!this.targetElement) { |
|
|
const { offsetHeight, offsetWidth } = this.elRef.nativeElement; |
|
|
const { offsetHeight, offsetWidth } = this.elRef.nativeElement; |
|
|
if (!offsetHeight && !offsetWidth && this.elRef.nativeElement.children?.length) { |
|
|
if (!offsetHeight && !offsetWidth && this.elRef.nativeElement.children?.length) { |
|
|
|