import { FormGroup , FormControl } from '@angular/forms' ; import { Component , OnInit , OnChanges , SimpleChanges , EventEmitter , ViewChild , Input , Output } from '@angular/core' ; import { DropDownElement , DropDownGroupElement } from '../shared/models/drop-down-element' ; @ Component ( { selector : 'drop-down' , templateUrl : './drop-down.component.html' , styleUrls : [ './drop-down.component.scss' ] , } ) export class DropDownComponent < T > implements OnInit , OnChanges { @ Input ( ) group : FormGroup ; @ Input ( ) control : FormControl ; @ Input ( ) name : string ; @ Input ( ) placeholder : string ; @ Input ( ) disabled : boolean ; @ Input ( ) highlightDirty : boolean ; @ Input ( ) size : null | 'small' | 'medium' | 'large' = 'medium' ; @ Input ( ) setDefault = true ; @ Input ( ) ariaLabel = '' ; @ Input ( ) ariaErrorId = '' ; @ Output ( ) value : EventEmitter < T > ; public hasFocus : boolean = false ; public selectedElement : DropDownElement < T > ; public empty : any ; public _options : DropDownGroupElement < T > [ ] | DropDownElement < T > [ ] ; public optionsGrouped : boolean ; @ ViewChild ( 'selectInput' ) selectInput : any ; constructor ( ) { this . value = new EventEmitter < T > ( ) ; } setControl ( ) { if ( this . group && this . name ) { this . control = < FormControl > this . group . controls [ this . name ] ; } } ngOnInit ( ) { this . setControl ( ) ; } ngOnChanges ( changes ) { if ( changes [ 'group' ] || changes [ 'name' ] ) { this . setControl ( ) ; } } @ Input ( ) set options ( value ) { this . _options = [ ] ; if ( ! value || value . length === 0 ) { delete this . selectedElement ; return ; } this . optionsGrouped = ( value [ 0 ] as DropDownGroupElement < T > ) . dropDownElements !== undefined ; let controlMatchingOption = null ; let defaultOption = null ; let autoDefaultOption = null ; let optionCount = 0 ; if ( this . optionsGrouped ) { const options = [ ] ; const inputs = value as DropDownGroupElement < T > [ ] ; inputs . forEach ( optGroup => { const optionsGroup = { displayLabel : optGroup . displayLabel , dropDownElements : [ ] , } ; optGroup . dropDownElements . forEach ( opt => { const option = { id : optionCount ++ , displayLabel : opt . displayLabel , value : opt . value , default : opt . default , } ; if ( this . control && this . control . value === opt . value ) { controlMatchingOption = option ; } if ( opt . default ) { defaultOption = option ; } if ( optionCount === 1 && this . setDefault ) { autoDefaultOption = option ; } optionsGroup . dropDownElements . push ( option ) ; } ) ; options . push ( optionsGroup ) ; } ) ; this . _options = options ; } else { const options = [ ] ; const inputs = value as DropDownElement < T > [ ] ; inputs . forEach ( ( opt , ind , arr ) => { const option = { id : optionCount ++ , displayLabel : opt . displayLabel , value : opt . value , default : opt . default , } ; if ( this . control && this . control . value === opt . value ) { controlMatchingOption = option ; } if ( opt . default ) { defaultOption = option ; } if ( optionCount === 1 && ( this . setDefault || arr . length === 1 ) ) { autoDefaultOption = option ; } options . push ( option ) ; } ) ; this . _options = options ; } if ( optionCount === 0 ) { delete this . selectedElement ; } else if ( ! ! this . control && this . control . value !== null ) { if ( ! controlMatchingOption ) { delete this . selectedElement ; } else { this . onSelectValue ( controlMatchingOption . value ) ; } } else { const defaultOpt = defaultOption || ( this . setDefault && autoDefaultOption ) ; if ( ! defaultOpt ) { delete this . selectedElement ; } else { if ( ! this . control ) { this . onSelect ( defaultOpt . id . toString ( ) ) ; } else { this . control . setValue ( defaultOpt . value ) ; this . onSelectValue ( defaultOpt . value ) ; } } } } @ Input ( ) set resetOnChange ( _ ) { delete this . selectedElement ; } @ Input ( ) set selectedValue ( value ) { if ( this . selectedElement . value !== value && value ) { this . onSelectValue ( value ) ; } } onSelect ( id ) { let element = null ; if ( this . optionsGrouped ) { ( this . _options as DropDownGroupElement < T > [ ] ) . forEach ( g => { element = element || g . dropDownElements . find ( e => e . id . toString ( ) === id ) ; } ) ; } else { element = ( this . _options as DropDownElement < T > [ ] ) . find ( e => e . id . toString ( ) === id ) ; } this . selectedElement = element ; this . value . emit ( element . value ) ; } onSelectValue ( value ) { let element = null ; if ( this . optionsGrouped ) { ( this . _options as DropDownGroupElement < T > [ ] ) . forEach ( g => { element = element || g . dropDownElements . find ( e => e . value === value ) ; } ) ; } else { element = ( this . _options as DropDownElement < T > [ ] ) . find ( e => e . value === value ) ; } this . selectedElement = element ; this . value . emit ( element . value ) ; } focus ( ) { if ( this . selectInput ) { this . selectInput . nativeElement . focus ( ) ; } } }