import { Directive , Input , TemplateRef , ElementRef , ViewContainerRef , ComponentFactoryResolver , Renderer2 , ChangeDetectionStrategy , ViewEncapsulation , ChangeDetectorRef , Component , ComponentFactory , ViewChild , SimpleChanges , OnInit , OnChanges , AfterViewInit , } from '@angular/core' ; import { slideMotion } from 'ng-zorro-antd/core/animation' ; import { CdkConnectedOverlay , CdkOverlayOrigin , ConnectedOverlayPositionChange , ConnectionPositionPair , } from '@angular/cdk/overlay' ; @ Component ( { selector : 'nsSlideoutCmp' , animations : [ slideMotion ] , changeDetection : ChangeDetectionStrategy . OnPush , encapsulation : ViewEncapsulation . None , preserveWhitespaces : false , template : `
    <ng-template
      #overlay="cdkConnectedOverlay"
      cdkConnectedOverlay
      [cdkConnectedOverlayOrigin]="origin"
      [cdkConnectedOverlayOpen]="nsVisible"
      (positionChange)="onPositionChange($event)"
    >
      <div [@slideMotion]="slideMotionState">
        <ng-container *ngTemplateOutlet="nsSlideoutContent"></ng-container>
      </div>
    </ng-template>
  ` , } ) export class NsSlideoutComponent { constructor ( private cdr ) { } nsSlideoutContent : TemplateRef < void > ; origin : CdkOverlayOrigin ; @ ViewChild ( 'overlay' , { static : false } ) overlay : CdkConnectedOverlay ; @ Input ( ) nsVisible : boolean ; slideMotionState = 'top' ; updateByDirective ( ) { this . cdr . detectChanges ( ) ; Promise . resolve ( ) . then ( ( ) => { this . updatePosition ( ) ; } ) ; } setOverlayOrigin ( origin ) { this . origin = origin ; this . cdr . markForCheck ( ) ; } onPositionChange ( position ) { this . slideMotionState = this . getSlideMotionState ( position ) ; this . cdr . detectChanges ( ) ; } updatePosition ( ) { if ( this . origin && this . overlay && this . overlay . overlayRef ) { this . overlay . overlayRef . updatePosition ( ) ; } } getSlideMotionState ( position ) { return position . connectionPair . overlayY === 'bottom' ? 'top' : 'bottom' ; } } @ Directive ( { selector : '[nsSlideout]' , } ) export class NsSlideoutDirective implements OnInit , OnChanges , AfterViewInit { constructor ( private elementRef , private hostView , private resolver , private renderer ) { } @ Input ( ) nsSlideoutContent : TemplateRef < void > ; @ Input ( ) nsVisible : boolean ; componentFactory : ComponentFactory < NsSlideoutComponent > ; component : NsSlideoutComponent ; ngOnInit ( ) { this . componentFactory = this . resolver . resolveComponentFactory ( NsSlideoutComponent ) ; } ngAfterViewInit ( ) { this . createComponent ( ) ; } ngOnChanges ( changes ) { if ( this . component ) { this . updateChangedProperties ( ) ; } } private createComponent ( ) { const componentRef = this . hostView . createComponent ( this . componentFactory ) ; this . component = componentRef . instance ; this . renderer . removeChild ( this . renderer . parentNode ( this . elementRef . nativeElement ) , componentRef . location . nativeElement ) ; this . component . setOverlayOrigin ( { elementRef : this . elementRef } ) ; this . updateChangedProperties ( ) ; } private updateChangedProperties ( ) { this . updateComponentValue ( 'nsSlideoutContent' , this . nsSlideoutContent ) ; this . updateComponentValue ( 'nsVisible' , this . nsVisible ) ; this . component . updateByDirective ( ) ; } private updateComponentValue ( key , value ) { if ( typeof value !== 'undefined' ) { this . component [ key ] = value ; } } }