diff --git a/src/material/sort/sort-header.ts b/src/material/sort/sort-header.ts index e6071c26382a..ad584d8ca606 100644 --- a/src/material/sort/sort-header.ts +++ b/src/material/sort/sort-header.ts @@ -139,7 +139,7 @@ export class MatSortHeader extends _MatSortHeaderMixinBase private _disableClear: boolean; constructor(public _intl: MatSortHeaderIntl, - changeDetectorRef: ChangeDetectorRef, + private _changeDetectorRef: ChangeDetectorRef, @Optional() public _sort: MatSort, @Inject('MAT_SORT_HEADER_COLUMN_DEF') @Optional() public _columnDef: MatSortHeaderColumnDef, @@ -155,20 +155,7 @@ export class MatSortHeader extends _MatSortHeaderMixinBase throw getSortHeaderNotContainedWithinSortError(); } - this._rerenderSubscription = merge(_sort.sortChange, _sort._stateChanges, _intl.changes) - .subscribe(() => { - if (this._isSorted()) { - this._updateArrowDirection(); - } - - // If this header was recently active and now no longer sorted, animate away the arrow. - if (!this._isSorted() && this._viewState && this._viewState.toState === 'active') { - this._disableViewStateAnimation = false; - this._setAnimationTransitionState({fromState: 'active', toState: this._arrowDirection}); - } - - changeDetectorRef.markForCheck(); - }); + this._handleStateChanges(); } ngOnInit() { @@ -234,23 +221,9 @@ export class MatSortHeader extends _MatSortHeaderMixinBase /** Triggers the sort on this sort header and removes the indicator hint. */ _handleClick() { - if (this._isDisabled()) { return; } - - this._sort.sort(this); - - // Do not show the animation if the header was already shown in the right position. - if (this._viewState.toState === 'hint' || this._viewState.toState === 'active') { - this._disableViewStateAnimation = true; + if (!this._isDisabled()) { + this._sort.sort(this); } - - // If the arrow is now sorted, animate the arrow into place. Otherwise, animate it away into - // the direction it is facing. - const viewState: ArrowViewStateTransition = this._isSorted() ? - {fromState: this._arrowDirection, toState: 'active'} : - {fromState: 'active', toState: this._arrowDirection}; - this._setAnimationTransitionState(viewState); - - this._showIndicatorHint = false; } /** Whether this MatSortHeader is currently sorted in either ascending or descending order. */ @@ -307,6 +280,32 @@ export class MatSortHeader extends _MatSortHeaderMixinBase return !this._isDisabled() || this._isSorted(); } + /** Handles changes in the sorting state. */ + private _handleStateChanges() { + this._rerenderSubscription = + merge(this._sort.sortChange, this._sort._stateChanges, this._intl.changes).subscribe(() => { + if (this._isSorted()) { + this._updateArrowDirection(); + + // Do not show the animation if the header was already shown in the right position. + if (this._viewState.toState === 'hint' || this._viewState.toState === 'active') { + this._disableViewStateAnimation = true; + } + + this._setAnimationTransitionState({fromState: this._arrowDirection, toState: 'active'}); + this._showIndicatorHint = false; + } + + // If this header was recently active and now no longer sorted, animate away the arrow. + if (!this._isSorted() && this._viewState && this._viewState.toState === 'active') { + this._disableViewStateAnimation = false; + this._setAnimationTransitionState({fromState: 'active', toState: this._arrowDirection}); + } + + this._changeDetectorRef.markForCheck(); + }); + } + static ngAcceptInputType_disableClear: BooleanInput; static ngAcceptInputType_disabled: BooleanInput; } diff --git a/src/material/sort/sort.spec.ts b/src/material/sort/sort.spec.ts index 0e2cedc854ba..ee9a52cbb935 100644 --- a/src/material/sort/sort.spec.ts +++ b/src/material/sort/sort.spec.ts @@ -196,6 +196,15 @@ describe('MatSort', () => { component.dispatchMouseEvent('defaultA', 'mouseenter'); component.expectViewAndDirectionStates(expectedStates); }); + + it('should be correct when sorting programmatically', () => { + component.active = 'defaultB'; + component.direction = 'asc'; + fixture.detectChanges(); + + expectedStates.set('defaultB', {viewState: 'asc-to-active', arrowDirection: 'active-asc'}); + component.expectViewAndDirectionStates(expectedStates); + }); }); it('should be able to cycle from asc -> desc from either start point', () => { diff --git a/tools/public_api_guard/material/sort.d.ts b/tools/public_api_guard/material/sort.d.ts index 21ccfc1bce04..f0339f72e78b 100644 --- a/tools/public_api_guard/material/sort.d.ts +++ b/tools/public_api_guard/material/sort.d.ts @@ -64,7 +64,7 @@ export declare class MatSortHeader extends _MatSortHeaderMixinBase implements Ca set disableClear(v: boolean); id: string; start: 'asc' | 'desc'; - constructor(_intl: MatSortHeaderIntl, changeDetectorRef: ChangeDetectorRef, _sort: MatSort, _columnDef: MatSortHeaderColumnDef, _focusMonitor: FocusMonitor, _elementRef: ElementRef); + constructor(_intl: MatSortHeaderIntl, _changeDetectorRef: ChangeDetectorRef, _sort: MatSort, _columnDef: MatSortHeaderColumnDef, _focusMonitor: FocusMonitor, _elementRef: ElementRef); _getAriaSortAttribute(): "ascending" | "descending" | null; _getArrowDirectionState(): string; _getArrowViewState(): string;