import { Directive , Input , OnInit , OnDestroy , ComponentRef , ComponentFactoryResolver , ViewContainerRef , TemplateRef , Renderer2 , EmbeddedViewRef } from '@angular/core' ; import { BlockUIContentComponent } from '../components/block-ui-content/block-ui-content.component' ; import { BlockUIInstanceService } from '../services/block-ui-instance.service' ; import { BlockUIDefaultName } from '../constants/block-ui-default-name.constant' ; import { BlockUIService } from '../services/block-ui.service' ; @ Directive ( { selector : '[blockUI]' } ) export class BlockUIDirective implements OnInit , OnDestroy { private blockUIComponentRef : ComponentRef < BlockUIContentComponent > ; blockTarget : string ; message : any ; template : any ; delayStart : any ; delayStop : any ; @ Input ( ) set blockUI ( name ) { this . blockTarget = name ; } ; @ Input ( ) set blockUIMessage ( message ) { this . message = message ; } ; @ Input ( ) set blockUITemplate ( template ) { this . template = template ; } ; @ Input ( ) set blockUIDelayStart ( delayStart ) { this . delayStart = delayStart ? Number ( delayStart ) : null ; } ; @ Input ( ) set blockUIDelayStop ( delayStop ) { this . delayStop = delayStop ? Number ( delayStop ) : null ; } ; constructor ( private blockUIService , private blockUIInstanceService , private viewRef , private templateRef , private renderer , private componentFactoryResolver ) { } ngOnInit ( ) { try { this . viewRef . createEmbeddedView ( this . templateRef ) ; const parentElement = this . getParentElement ( ) ; if ( parentElement && ! this . isComponentInTemplate ( parentElement ) ) { this . renderer . addClass ( parentElement , 'block-ui__element' ) ; this . blockUIComponentRef = this . createComponent ( ) ; let blockUIContent = this . findContentNode ( this . viewRef . element . nativeElement ) ; if ( blockUIContent ) { const settings = this . blockUIInstanceService . getSettings ( ) ; parentElement . appendChild ( blockUIContent ) ; this . blockUIComponentRef . instance . className = 'block-ui-wrapper--element' ; this . blockUIComponentRef . instance . name = this . blockTarget || BlockUIDefaultName ; if ( this . message ) this . blockUIComponentRef . instance . defaultMessage = this . message ; if ( this . delayStart ) this . blockUIComponentRef . instance . delayStart = this . delayStart ; if ( this . delayStop ) this . blockUIComponentRef . instance . delayStop = this . delayStop ; if ( this . template || settings . template ) this . blockUIComponentRef . instance . templateCmp = this . template || settings . template ; } } } catch ( error ) { console . error ( 'ng-block-ui:' , error ) ; } } private isComponentInTemplate ( element ) { const targetElement = element || { } ; let { children } = targetElement ; children = Array . from ( children || [ ] ) . reverse ( ) ; return children . some ( ( el ) => el && el . localName === 'block-ui' ) ; } private getParentElement ( ) { const embeddedView = this . viewRef . get ( 0 ) as EmbeddedViewRef < any > ; return embeddedView . rootNodes [ 0 ] ; } private findContentNode ( element ) { const nextSibling = element . nextSibling || { } ; const previousSibling = element . previousSibling || { } ; return [ nextSibling , nextSibling . nextSibling , previousSibling , previousSibling . previousSibling ] . find ( ( e ) => e && e . localName === 'block-ui-content' ) ; } private createComponent ( ) { const resolvedBlockUIComponent = this . componentFactoryResolver . resolveComponentFactory ( BlockUIContentComponent ) ; return this . viewRef . createComponent ( resolvedBlockUIComponent ) ; } ngOnDestroy ( ) { if ( this . blockTarget ) { this . blockUIService . reset ( this . blockTarget ) ; } } }