import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ElementRef, EventEmitter, Input, NgZone, OnDestroy, Output, Renderer2, TemplateRef, ViewChild } from '@angular/core'; import {AnimationEvent} from '../animations/animations.interface'; import {removeListeners} from '../helpers'; /* * */ @Component({ selector: 'mk-dropdown-toggle', template: '', changeDetection: ChangeDetectionStrategy.OnPush }) export class DropdownToggleComponent { @ViewChild('templateRef') public templateRef: TemplateRef; @ContentChild('toggleElement') public toggleElement: ElementRef; } /* * */ @Component({ selector: 'mk-dropdown-menu', template: '', changeDetection: ChangeDetectionStrategy.OnPush }) export class DropdownMenuComponent { @ViewChild('templateRef') public templateRef: TemplateRef; } /* * */ @Component({ selector: 'mk-dropdown, [mk-dropdown]', templateUrl: './dropdown.component.html', styleUrls: ['./dropdown.component.css'], changeDetection: ChangeDetectionStrategy.OnPush }) export class DropdownComponent implements AfterViewInit, OnDestroy { private documentClickListener: Function; private listeners = []; @Input() public buttonStyleClass = 'btn dropdown-toggle'; @Input() public buttonBackgroudColor = 'default'; @Input() public contentStyleClass = 'dropdown-menu'; @Input() public isCollapsed = true; @Input() public isWrapper = true; @Input() public styleClass = 'dropdown'; @Input() public toggleElement: Element; @Input() public toggleText: string; @Output() public onCollapseStart = new EventEmitter(); @Output() public onCollapseDone = new EventEmitter(); @ContentChild(DropdownToggleComponent) public dropdownToggleComponent: DropdownToggleComponent; @ContentChild(DropdownMenuComponent) public dropdownMenuComponent: DropdownMenuComponent; @ViewChild('toggleElement') private defaultToggleElement: ElementRef; /** * @method constructor * @param changeDetectorRef [description] * @param elementRef [description] * @param ngZone [description] * @param renderer2 [description] */ constructor( private changeDetectorRef: ChangeDetectorRef, private elementRef: ElementRef, private ngZone: NgZone, private renderer2: Renderer2 ) {} /** * @method ngAfterViewInit */ ngAfterViewInit() { const toggleNativeElement = this.dropdownToggleComponent && this.dropdownToggleComponent.toggleElement ? this.dropdownToggleComponent.toggleElement.nativeElement : this.toggleElement ? this.toggleElement : this.defaultToggleElement ? this.defaultToggleElement.nativeElement : null; if (toggleNativeElement) { this.ngZone.runOutsideAngular(() => { this.listeners.push(this.renderer2.listen(toggleNativeElement, 'click', (event: Event) => { this.toggleDropdown(event); this.changeDetectorRef.detectChanges(); })); }); } } /** * @method ngOnDestroy */ ngOnDestroy() { this.unBindDocumentClickListener(); removeListeners(this.listeners); } /** * [toggle description] * @method toggle * @param event [description] */ public toggleDropdown(event: Event): void { event.preventDefault(); this.isCollapsed = !this.isCollapsed; if (!this.isCollapsed) { this.ngZone.runOutsideAngular(() => { setTimeout (() => { this.bindDocumentClickListener(); }); }); } else { this.unBindDocumentClickListener(); } } /** * [collapseStart description] * @method collapseStart * @param event [description] */ public collapseStart(event: AnimationEvent): void { this.onCollapseStart.emit(event); } /** * [collapseDone description] * @method collapseDone * @param event [description] */ public collapseDone(event: AnimationEvent): void { this.onCollapseStart.emit(event); } /** * [bindDocumentClickListener description] * @method bindDocumentClickListener */ private bindDocumentClickListener(): void { this.ngZone.runOutsideAngular(() => { this.documentClickListener = this.renderer2.listen('document', 'click', () => { if (!this.isCollapsed) { this.isCollapsed = true; this.unBindDocumentClickListener(); this.changeDetectorRef.detectChanges(); } }); }); } /** * [unBindDocumentClickListener description] * @method unBindDocumentClickListener */ private unBindDocumentClickListener(): void { if (this.documentClickListener) { this.documentClickListener(); } } }