import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, Inject, Input, OnChanges, OnDestroy, Output, Renderer2, ViewChild, } from '@angular/core'; import { DropdownBoxOptionsInterface, } from './../../models/index'; import { fadeInOutAnimation, } from './../../helpers/animations/index'; @Component({ animations: [ fadeInOutAnimation(), ], changeDetection: ChangeDetectionStrategy.OnPush, selector: 'dropdown-box-component', styleUrls: [ './dropdown-box.component.scss', ], templateUrl: 'dropdown-box.component.template.pug', }) export class DropdownBoxComponent implements OnChanges, OnDestroy { @ViewChild('dropDownRoot') public dropDownRoot: ElementRef; public isOpen = false; public selectedOption: DropdownBoxOptionsInterface; @Input() public options: DropdownBoxOptionsInterface[]; @Input() public value: string; @Input() public placeholder: string; @Output() public onChange = new EventEmitter(); public get applyMinHeight() { return Boolean(this.options.length > 4); } public rendererWindowUnlisten: () => void; constructor( @Inject('window') private _window: Window, private _renderer: Renderer2, private _changeDetectorRef: ChangeDetectorRef, ) {} public onClickOutside(event) { if ( !this.dropDownRoot.nativeElement.contains(event.target) ) { this.isOpen = false; } if (!this.isOpen) { this.rendererWindowUnlisten(); this.rendererWindowUnlisten = undefined; } this._changeDetectorRef.markForCheck(); } public ngOnChanges() { this.selectedOption = this.options.find( (option) => option.value === this.value, ); } public ngOnDestroy() { if (this.rendererWindowUnlisten) { this.rendererWindowUnlisten(); } } public onClick(selectedValue: string, selectedLabel: string) { if (this.rendererWindowUnlisten) { this.rendererWindowUnlisten(); this.rendererWindowUnlisten = undefined; } this.isOpen = !this.isOpen; this.rendererWindowUnlisten = this._renderer.listen( this._window, 'click', this.onClickOutside.bind(this), ); if ( (selectedLabel && !this.selectedOption) || (selectedLabel && (selectedLabel !== this.selectedOption.label)) ) { this._setValue(selectedValue, selectedLabel); } } private _setValue(newValue: string, newLabel: string) { this.selectedOption = { label: newLabel, value: newValue, } as DropdownBoxOptionsInterface; this.onChange.emit(newValue); if (this.rendererWindowUnlisten) { this.rendererWindowUnlisten(); this.rendererWindowUnlisten = undefined; } } }