diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/loading/loading.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/loading/loading.component.ts new file mode 100644 index 00000000000..6c2201e940f --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/loading/loading.component.ts @@ -0,0 +1,39 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'abp-loading', + template: ` +
+ +
+ `, + styles: [ + ` + .abp-loading { + background: rgba(0, 0, 0, 0.3); + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + z-index: 1040; + } + + .abp-loading .abp-spinner { + position: absolute; + top: 50%; + left: 50%; + -moz-transform: translateX(-50%) translateY(-50%); + -o-transform: translateX(-50%) translateY(-50%); + -ms-transform: translateX(-50%) translateY(-50%); + -webkit-transform: translateX(-50%) translateY(-50%); + transform: translateX(-50%) translateY(-50%); + } + `, + ], +}) +export class LoadingComponent implements OnInit { + constructor() {} + + ngOnInit() {} +} diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/loading.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/loading.directive.ts new file mode 100644 index 00000000000..d38b3713b75 --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/loading.directive.ts @@ -0,0 +1,74 @@ +import { + Directive, + ElementRef, + AfterViewInit, + ViewContainerRef, + ComponentFactoryResolver, + Input, + Injector, + ComponentRef, + ComponentFactory, + HostBinding, + EmbeddedViewRef, + Renderer2, + OnInit, +} from '@angular/core'; +import { LoadingComponent } from '../components/loading/loading.component'; + +@Directive({ selector: '[abpLoading]' }) +export class LoadingDirective implements OnInit { + private _loading: boolean; + + @HostBinding('style.position') + position = 'relative'; + + @Input('abpLoading') + get loading(): boolean { + return this._loading; + } + + set loading(newValue: boolean) { + setTimeout(() => { + if (!this.componentRef) { + this.componentRef = this.cdRes + .resolveComponentFactory(LoadingComponent) + .create(this.injector); + } + + if (newValue && !this.rootNode) { + this.rootNode = (this.componentRef.hostView as EmbeddedViewRef).rootNodes[0]; + this.targetElement.appendChild(this.rootNode); + } else { + this.renderer.removeChild(this.rootNode.parentElement, this.rootNode); + this.rootNode = null; + } + + this._loading = newValue; + }, 0); + } + + @Input('abpLoadingTargetElement') + targetElement: HTMLElement; + + componentRef: ComponentRef; + rootNode: HTMLDivElement; + + constructor( + private elRef: ElementRef, + private vcRef: ViewContainerRef, + private cdRes: ComponentFactoryResolver, + private injector: Injector, + private renderer: Renderer2, + ) {} + + ngOnInit() { + if (!this.targetElement) { + const { offsetHeight, offsetWidth } = this.elRef.nativeElement; + if (!offsetHeight && !offsetWidth && this.elRef.nativeElement.children.length) { + this.targetElement = this.elRef.nativeElement.children[0] as HTMLElement; + } else { + this.targetElement = this.elRef.nativeElement; + } + } + } +}