Skip to content

Commit 06f7e28

Browse files
committed
fix(tabs): disabled tab link not preventing router navigation
Fixes users being able to navigate to a new route by clicking on a disabled `mat-tab-link`. Fixes #10354.
1 parent 6273d6a commit 06f7e28

File tree

4 files changed

+14
-22
lines changed

4 files changed

+14
-22
lines changed

src/demo-app/tabs/tabs-demo.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ <h1>Tab Nav Bar</h1>
1414
[active]="rla.isActive">
1515
{{tabLink.label}}
1616
</a>
17-
<a mat-tab-link disabled>Disabled Link</a>
17+
<a routerLink="foggy-tab" mat-tab-link disabled>Disabled Link</a>
1818
</nav>
1919
<router-outlet></router-outlet>
2020
</div>
@@ -308,5 +308,5 @@ <h1>Lazy Loaded Tabs</h1>
308308
</mat-tab>
309309
<mat-tab label="Third">
310310
<counter></counter>
311-
</mat-tab>
311+
</mat-tab>
312312
</mat-tab-group>

src/lib/tabs/tab-nav-bar/tab-nav-bar.scss

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@
1717
text-decoration: none; // Removes anchor underline styling
1818
position: relative;
1919
overflow: hidden; // Keeps the ripple from extending outside the element bounds
20+
21+
&.mat-tab-disabled {
22+
// We use `pointer-events` to make the element unclickable when it's disabled, rather than
23+
// preventing the default action through JS, because we can't prevent the action reliably
24+
// due to other directives potentially registering their events earlier. This shouldn't cause
25+
// the user to click through, because we always have a `.mat-tab-links` behind the link.
26+
pointer-events: none;
27+
}
2028
}
2129

2230
@media ($mat-xsmall) {

src/lib/tabs/tab-nav-bar/tab-nav-bar.spec.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {async, ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing';
22
import {Component, ViewChild} from '@angular/core';
33
import {By} from '@angular/platform-browser';
4-
import {dispatchFakeEvent, dispatchMouseEvent, createMouseEvent} from '@angular/cdk/testing';
4+
import {dispatchFakeEvent, dispatchMouseEvent} from '@angular/cdk/testing';
55
import {Direction, Directionality} from '@angular/cdk/bidi';
66
import {Subject} from 'rxjs/Subject';
77
import {MatTabLink, MatTabNav, MatTabsModule} from '../index';
@@ -125,21 +125,15 @@ describe('MatTabNavBar', () => {
125125
.toBe(true, 'Expected element to no longer be keyboard focusable if disabled.');
126126
});
127127

128-
it('should prevent default action for clicks if links are disabled', () => {
128+
it('should make disabled links unclickable', () => {
129129
const tabLinkElement = fixture.debugElement.query(By.css('a')).nativeElement;
130130

131-
const mouseEvent = createMouseEvent('click');
132-
spyOn(mouseEvent, 'preventDefault');
133-
tabLinkElement.dispatchEvent(mouseEvent);
134-
expect(mouseEvent.preventDefault).not.toHaveBeenCalled();
131+
expect(getComputedStyle(tabLinkElement).pointerEvents).not.toBe('none');
135132

136133
fixture.componentInstance.disabled = true;
137134
fixture.detectChanges();
138135

139-
const mouseEventWhileDisabled = createMouseEvent('click');
140-
spyOn(mouseEventWhileDisabled, 'preventDefault');
141-
tabLinkElement.dispatchEvent(mouseEventWhileDisabled);
142-
expect(mouseEventWhileDisabled.preventDefault).toHaveBeenCalled();
136+
expect(getComputedStyle(tabLinkElement).pointerEvents).toBe('none');
143137
});
144138

145139
it('should show ripples for tab links', () => {

src/lib/tabs/tab-nav-bar/tab-nav-bar.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,6 @@ export const _MatTabLinkMixinBase =
188188
'[attr.tabIndex]': 'tabIndex',
189189
'[class.mat-tab-disabled]': 'disabled',
190190
'[class.mat-tab-label-active]': 'active',
191-
'(click)': '_handleClick($event)'
192191
}
193192
})
194193
export class MatTabLink extends _MatTabLinkMixinBase
@@ -249,13 +248,4 @@ export class MatTabLink extends _MatTabLinkMixinBase
249248
ngOnDestroy() {
250249
this._tabLinkRipple._removeTriggerEvents();
251250
}
252-
253-
/**
254-
* Handles the click event, preventing default navigation if the tab link is disabled.
255-
*/
256-
_handleClick(event: MouseEvent) {
257-
if (this.disabled) {
258-
event.preventDefault();
259-
}
260-
}
261251
}

0 commit comments

Comments
 (0)