import { AfterContentInit , Component , ContentChildren , EventEmitter , Input , OnDestroy , Output , QueryList } from '@angular/core' ; import { takeUntil } from 'rxjs/operators' ; import { Subject } from 'rxjs' ; import { SelectionService } from '../../directives/selection/selection.service' ; import { MultipleSelectListStrategy } from './strategies/multiple-select-list.strategy' ; import { SelectListItemComponent } from './select-list-item/select-list-item.component' ; import { SingleSelectListStrategy } from './strategies/single-select-list.strategy' ; @ Component ( { selector : 'ux-select-list' , templateUrl : './select-list.component.html' , providers : [ SelectionService ] , host : { role : 'list' } } ) export class SelectListComponent < T > implements AfterContentInit , OnDestroy { /** Determine if we allow multiple items to be selected */ @ Input ( ) set multiple ( multiple ) { this . _selection . strategy . deselectAll ( ) ; this . _selection . setStrategy ( multiple ? new MultipleSelectListStrategy < T > ( ) : new SingleSelectListStrategy < T > ( ) ) ; } /** Set the selected items */ @ Input ( ) set selected ( selected ) { if ( this . _selection . selection$ . value === selected ) { return ; } if ( Array . isArray ( selected ) && selected . length === 0 && this . _selection . selection$ . value . length === 0 ) { return ; } if ( Array . isArray ( selected ) ) { this . _selection . selectOnly ( ... selected ) ; } else { this . _selection . selectOnly ( selected as T ) ; } } /** Emit when the selection changes */ @ Output ( ) selectedChange = new EventEmitter < ReadonlyArray < T > > ( ) ; /** Find all select list items */ @ ContentChildren ( SelectListItemComponent ) items : QueryList < SelectListItemComponent < T > > ; /** Automatically unsubscribe all observables */ private _onDestroy = new Subject < void > ( ) ; constructor ( private _selection ) { this . _selection . setStrategy ( new SingleSelectListStrategy < T > ( ) ) ; this . _selection . selection$ . pipe ( takeUntil ( this . _onDestroy ) ) . subscribe ( selection => this . selectedChange . emit ( selection ) ) ; } ngAfterContentInit ( ) { this . _selection . dataset = this . items . map ( item => item . data ) ; this . items . changes . pipe ( takeUntil ( this . _onDestroy ) ) . subscribe ( ( ) => this . _selection . dataset = this . items . map ( item => item . data ) ) ; } ngOnDestroy ( ) { this . _onDestroy . next ( ) ; this . _onDestroy . complete ( ) ; } }