import { Directive , Input , OnDestroy , TemplateRef } from '@angular/core' ; import { Subject } from 'rxjs' ; @ Directive ( { selector : '[uxColumnSorting]' } ) export class ColumnSortingDirective implements OnDestroy { /** If set to true the column will sort by only this column, removing sorting from all others. */ @ Input ( ) singleSort : boolean ; /** Provide a custom template for the sort indicator */ @ Input ( ) sortIndicator : TemplateRef < ColumnSortingIndicatorContext > ; /** Emit the current sort state for all columns within the table */ events = new Subject < ReadonlyArray < ColumnSortingOrder > > ( ) ; /** Store the current sort state for all columns within the table */ order : ReadonlyArray < ColumnSortingOrder > = [ ] ; ngOnDestroy ( ) { this . events . complete ( ) ; } /** Toggle the sorting state of a column */ toggleColumn ( sorting ) { this . order = this . singleSort ? this . toggleSingleColumn ( sorting ) : this . toggleMultipleColumn ( sorting ) ; this . events . next ( this . order ) ; return this . order ; } /** Explicitly set the column state */ setColumnState ( key , state ) { if ( this . order . find ( column => column . key === key && column . state === state ) ) { return ; } if ( this . singleSort && state !== ColumnSortingState . NoSort ) { this . order = [ ] ; } else { this . order = this . order . filter ( column => column . key !== key ) ; } if ( state === ColumnSortingState . Ascending || state === ColumnSortingState . Descending ) { this . order = [ ... this . order , { key , state } ] ; } } /** Toggle the sorting state of a column when using single select */ private toggleSingleColumn ( sorting ) { return sorting . state === ColumnSortingState . NoSort ? [ ] : [ { key : sorting . key , state : sorting . state } ] ; } /** Toggle the sorting state of a column when using multiple select */ private toggleMultipleColumn ( sorting ) { const idx = this . order . findIndex ( column => column . key === sorting . key ) ; if ( idx === - 1 && sorting . state !== ColumnSortingState . NoSort ) { return [ ... this . order , { key : sorting . key , state : sorting . state } ] ; } if ( sorting . state === ColumnSortingState . Ascending || sorting . state === ColumnSortingState . Descending ) { return [ ... this . order . filter ( _column => _column . key !== sorting . key ) , { key : sorting . key , state : sorting . state } ] ; } return this . order . filter ( _column => _column . key !== sorting . key ) ; } } export interface ColumnSortingOrder { key : string ; state : ColumnSortingState ; } export enum ColumnSortingState { Ascending = 'ascending' , Descending = 'descending' , NoSort = 'none' } export interface ColumnSortingIndicatorContext { state : ColumnSortingState ; order : number ; }