import { ChangeDetectionStrategy , ChangeDetectorRef , Component , ElementRef , HostListener , Inject , Input , OnDestroy , OnInit , PLATFORM_ID , TemplateRef , ViewChild , } from '@angular/core' ; import { Subject , Subscription } from 'rxjs' ; import { debounceTime } from 'rxjs/operators' ; import { isPlatformBrowser } from '@angular/common' ; export interface AnchorPosition { top ? : string ; right ? : string ; bottom ? : string ; left ? : string ; } @ Component ( { selector : 'm-dropdownMenu' , changeDetection : ChangeDetectionStrategy . OnPush , templateUrl : 'dropdown-menu.component.html' , } ) export class DropdownMenuComponent implements OnInit , OnDestroy { @ Input ( ) menu : TemplateRef < any > ; @ Input ( ) triggerClass : string = '' ; @ Input ( ) menuClass : string = '' ; @ Input ( ) anchorPosition : AnchorPosition = { top : '100%' , left : '0' , } ; @ ViewChild ( 'triggerElement' ) triggerElement : ElementRef < HTMLSpanElement > ; @ ViewChild ( 'menuWrapperElement' ) menuWrapperElement : ElementRef < HTMLDivElement > ; isOpen : boolean = false ; protected windowSize$ : Subject < { width : number ; height : number ; } > = new Subject < { width : number ; height : number ; } > ( ) ; protected windowSizeSubscription : Subscription ; constructor ( protected cd , @ Inject ( PLATFORM_ID ) private platformId ) { } ngOnInit ( ) { this . windowSizeSubscription = this . windowSize$ . pipe ( debounceTime ( 250 ) ) . subscribe ( ( ) => this . calculatePosition ( ) ) ; } ngOnDestroy ( ) { this . windowSizeSubscription . unsubscribe ( ) ; } open ( $event ) { if ( $event ) { $event . preventDefault ( ) ; $event . stopPropagation ( ) ; } this . isOpen = true ; this . detectChanges ( ) ; this . calculatePosition ( ) ; } close ( $event ? ) { if ( $event ) { $event . preventDefault ( ) ; $event . stopPropagation ( ) ; } this . isOpen = false ; } get triggerCssClasses ( ) { const classList = [ 'm-dropdownMenu__trigger' , 'm-dropdownMenuTrigger--clickable' , ] ; if ( this . triggerClass ) { classList . push ( ... this . triggerClass . split ( ' ' ) . map ( className => className . trim ( ) ) . filter ( Boolean ) ) ; } return classList ; } get menuCssClasses ( ) { const classList = [ 'm-dropdownMenu__menu' ] ; if ( this . menuClass ) { classList . push ( ... this . menuClass . split ( ' ' ) . map ( className => className . trim ( ) ) . filter ( Boolean ) ) ; } return classList ; } @ HostListener ( 'window:resize' ) onWindowResize ( ) { this . calculatePosition ( ) ; } calculatePosition ( ) { } detectChanges ( ) { this . cd . markForCheck ( ) ; this . cd . detectChanges ( ) ; } }