Skip to content

Commit

Permalink
fix(material/tabs): avoid reference error (#25928)
Browse files Browse the repository at this point in the history
Moves the `_MatTabNavBase` class a bit further up in the file to try and avoid a reference error in some test setups.

Fixes #25918.

(cherry picked from commit f08f3aa)
  • Loading branch information
crisbeto committed Nov 4, 2022
1 parent a64186a commit 66632c9
Showing 1 changed file with 110 additions and 110 deletions.
220 changes: 110 additions & 110 deletions src/material/tabs/tab-nav-bar/tab-nav-bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,116 @@ import {MatPaginatedTabHeader, MatPaginatedTabHeaderItem} from '../paginated-tab
// Increasing integer for generating unique ids for tab nav components.
let nextUniqueId = 0;

/**
* Base class with all of the `MatTabNav` functionality.
* @docs-private
*/
@Directive()
export abstract class _MatTabNavBase
extends MatPaginatedTabHeader
implements AfterContentChecked, AfterContentInit, OnDestroy
{
/** Query list of all tab links of the tab navigation. */
abstract override _items: QueryList<MatPaginatedTabHeaderItem & {active: boolean; id: string}>;

/** Background color of the tab nav. */
@Input()
get backgroundColor(): ThemePalette {
return this._backgroundColor;
}

set backgroundColor(value: ThemePalette) {
const classList = this._elementRef.nativeElement.classList;
classList.remove(`mat-background-${this.backgroundColor}`);

if (value) {
classList.add(`mat-background-${value}`);
}

this._backgroundColor = value;
}

private _backgroundColor: ThemePalette;

/** Whether the ripple effect is disabled or not. */
@Input()
get disableRipple(): boolean {
return this._disableRipple;
}

set disableRipple(value: BooleanInput) {
this._disableRipple = coerceBooleanProperty(value);
}

private _disableRipple: boolean = false;

/** Theme color of the nav bar. */
@Input() color: ThemePalette = 'primary';

/**
* Associated tab panel controlled by the nav bar. If not provided, then the nav bar
* follows the ARIA link / navigation landmark pattern. If provided, it follows the
* ARIA tabs design pattern.
*/
@Input() tabPanel?: MatTabNavPanel;

constructor(
elementRef: ElementRef,
@Optional() dir: Directionality,
ngZone: NgZone,
changeDetectorRef: ChangeDetectorRef,
viewportRuler: ViewportRuler,
platform: Platform,
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string,
) {
super(elementRef, changeDetectorRef, viewportRuler, dir, ngZone, platform, animationMode);
}

protected _itemSelected() {
// noop
}

override ngAfterContentInit() {
// We need this to run before the `changes` subscription in parent to ensure that the
// selectedIndex is up-to-date by the time the super class starts looking for it.
this._items.changes.pipe(startWith(null), takeUntil(this._destroyed)).subscribe(() => {
this.updateActiveLink();
});

super.ngAfterContentInit();
}

/** Notifies the component that the active link has been changed. */
updateActiveLink() {
if (!this._items) {
return;
}

const items = this._items.toArray();

for (let i = 0; i < items.length; i++) {
if (items[i].active) {
this.selectedIndex = i;
this._changeDetectorRef.markForCheck();

if (this.tabPanel) {
this.tabPanel._activeTabId = items[i].id;
}

return;
}
}

// The ink bar should hide itself if no items are active.
this.selectedIndex = -1;
this._inkBar.hide();
}

_getRole(): string | null {
return this.tabPanel ? 'tablist' : this._elementRef.nativeElement.getAttribute('role');
}
}

// Boilerplate for applying mixins to MatTabLink.
const _MatTabLinkMixinBase = mixinTabIndex(mixinDisableRipple(mixinDisabled(class {})));

Expand Down Expand Up @@ -189,116 +299,6 @@ export class _MatTabLinkBase

const _MatTabLinkBaseWithInkBarItem = mixinInkBarItem(_MatTabLinkBase);

/**
* Base class with all of the `MatTabNav` functionality.
* @docs-private
*/
@Directive()
export abstract class _MatTabNavBase
extends MatPaginatedTabHeader
implements AfterContentChecked, AfterContentInit, OnDestroy
{
/** Query list of all tab links of the tab navigation. */
abstract override _items: QueryList<MatPaginatedTabHeaderItem & {active: boolean; id: string}>;

/** Background color of the tab nav. */
@Input()
get backgroundColor(): ThemePalette {
return this._backgroundColor;
}

set backgroundColor(value: ThemePalette) {
const classList = this._elementRef.nativeElement.classList;
classList.remove(`mat-background-${this.backgroundColor}`);

if (value) {
classList.add(`mat-background-${value}`);
}

this._backgroundColor = value;
}

private _backgroundColor: ThemePalette;

/** Whether the ripple effect is disabled or not. */
@Input()
get disableRipple(): boolean {
return this._disableRipple;
}

set disableRipple(value: BooleanInput) {
this._disableRipple = coerceBooleanProperty(value);
}

private _disableRipple: boolean = false;

/** Theme color of the nav bar. */
@Input() color: ThemePalette = 'primary';

/**
* Associated tab panel controlled by the nav bar. If not provided, then the nav bar
* follows the ARIA link / navigation landmark pattern. If provided, it follows the
* ARIA tabs design pattern.
*/
@Input() tabPanel?: MatTabNavPanel;

constructor(
elementRef: ElementRef,
@Optional() dir: Directionality,
ngZone: NgZone,
changeDetectorRef: ChangeDetectorRef,
viewportRuler: ViewportRuler,
platform: Platform,
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string,
) {
super(elementRef, changeDetectorRef, viewportRuler, dir, ngZone, platform, animationMode);
}

protected _itemSelected() {
// noop
}

override ngAfterContentInit() {
// We need this to run before the `changes` subscription in parent to ensure that the
// selectedIndex is up-to-date by the time the super class starts looking for it.
this._items.changes.pipe(startWith(null), takeUntil(this._destroyed)).subscribe(() => {
this.updateActiveLink();
});

super.ngAfterContentInit();
}

/** Notifies the component that the active link has been changed. */
updateActiveLink() {
if (!this._items) {
return;
}

const items = this._items.toArray();

for (let i = 0; i < items.length; i++) {
if (items[i].active) {
this.selectedIndex = i;
this._changeDetectorRef.markForCheck();

if (this.tabPanel) {
this.tabPanel._activeTabId = items[i].id;
}

return;
}
}

// The ink bar should hide itself if no items are active.
this.selectedIndex = -1;
this._inkBar.hide();
}

_getRole(): string | null {
return this.tabPanel ? 'tablist' : this._elementRef.nativeElement.getAttribute('role');
}
}

/**
* Navigation component matching the styles of the tab group header.
* Provides anchored navigation with animated ink bar.
Expand Down

0 comments on commit 66632c9

Please sign in to comment.