license import { coerceBooleanProperty } from '@angular/cdk/coercion' ; import { Directive , EventEmitter , Input , isDevMode , OnChanges , OnDestroy , OnInit , Output , } from '@angular/core' ; import { CanDisable , CanDisableCtor , HasInitialized , HasInitializedCtor , mixinDisabled , mixinInitialized , } from '@angular/material/core' ; import { Subject } from 'rxjs' ; import { SortDirection } from './sort-direction' ; import { getSortDuplicateSortableIdError , getSortHeaderMissingIdError , getSortInvalidDirectionError , } from './sort-errors' ; /** Interface for a directive that holds sorting state consumed by `MatSortHeader`. */ export interface MatSortable { /** The id of the column being sorted. */ id : string ; /** Starting sort direction. */ start : 'asc' | 'desc' ; /** Whether to disable clearing the sorting state. */ disableClear : boolean ; } /** The current sort state. */ export interface Sort { /** The id of the column being sorted. */ active : string ; /** The sort direction. */ direction : SortDirection ; } docs-private export class MatSortBase { } export const _MatSortMixinBase = mixinInitialized ( mixinDisabled ( MatSortBase ) ) ; /** Container for MatSortables to manage the sort state and provide default sort parameters. */ @ Directive ( { selector : '[matSort]' , exportAs : 'matSort' , inputs : [ 'disabled: matSortDisabled' ] } ) export class MatSort extends _MatSortMixinBase implements CanDisable , HasInitialized , OnChanges , OnDestroy , OnInit { /** Collection of all registered sortables that this directive manages. */ sortables = new Map < string , MatSortable > ( ) ; /** Used to notify any child components listening to state changes. */ readonly _stateChanges = new Subject < void > ( ) ; /** The id of the most recently sorted MatSortable. */ @ Input ( 'matSortActive' ) active : string ; /**
     * The direction to set when an MatSortable is initially sorted.
     * May be overriden by the MatSortable's sort start.
     */ @ Input ( 'matSortStart' ) start : 'asc' | 'desc' = 'asc' ; /** The sort direction of the currently active MatSortable. */ @ Input ( 'matSortDirection' ) get direction ( ) : SortDirection { return this . _direction ; } set direction ( direction ) { if ( isDevMode ( ) && direction && direction !== 'asc' && direction !== 'desc' ) { throw getSortInvalidDirectionError ( direction ) ; } this . _direction = direction ; } private _direction : SortDirection = '' ; /**
     * Whether to disable the user from clearing the sort by finishing the sort direction cycle.
     * May be overriden by the MatSortable's disable clear input.
     */ @ Input ( 'matSortDisableClear' ) get disableClear ( ) : boolean { return this . _disableClear ; } set disableClear ( v ) { this . _disableClear = coerceBooleanProperty ( v ) ; } private _disableClear : boolean ; /** Event emitted when the user changes either the active sort or sort direction. */ @ Output ( 'matSortChange' ) readonly sortChange : EventEmitter < Sort > = new EventEmitter < Sort > ( ) ; /**
     * Register function to be used by the contained MatSortables. Adds the MatSortable to the
     * collection of MatSortables.
     */ register ( sortable ) { if ( ! sortable . id ) { throw getSortHeaderMissingIdError ( ) ; } if ( this . sortables . has ( sortable . id ) ) { throw getSortDuplicateSortableIdError ( sortable . id ) ; } this . sortables . set ( sortable . id , sortable ) ; } /**
     * Unregister function to be used by the contained MatSortables. Removes the MatSortable from the
     * collection of contained MatSortables.
     */ deregister ( sortable ) { this . sortables . delete ( sortable . id ) ; } /** Sets the active sort id and determines the new sort direction. */ sort ( sortable ) { if ( this . active != sortable . id ) { this . active = sortable . id ; this . direction = sortable . start ? sortable . start : this . start ; } else { this . direction = this . getNextSortDirection ( sortable ) ; } this . sortChange . emit ( { active : this . active , direction : this . direction } ) ; } /** Returns the next sort direction of the active sortable, checking for potential overrides. */ getNextSortDirection ( sortable ) { if ( ! sortable ) { return '' ; } const disableClear = sortable . disableClear != null ? sortable . disableClear : this . disableClear ; let sortDirectionCycle = getSortDirectionCycle ( sortable . start || this . start , disableClear ) ; let nextDirectionIndex = sortDirectionCycle . indexOf ( this . direction ) + 1 ; if ( nextDirectionIndex >= sortDirectionCycle . length ) { nextDirectionIndex = 0 ; } return sortDirectionCycle [ nextDirectionIndex ] ; } ngOnInit ( ) { this . _markInitialized ( ) ; } ngOnChanges ( ) { this . _stateChanges . next ( ) ; } ngOnDestroy ( ) { this . _stateChanges . complete ( ) ; } } /** Returns the sort direction cycle to use given the provided parameters of order and clear. */ function getSortDirectionCycle ( start , disableClear ) { let sortOrder = [ 'asc' , 'desc' ] ; if ( start == 'desc' ) { sortOrder . reverse ( ) ; } if ( ! disableClear ) { sortOrder . push ( '' ) ; } return sortOrder ; }