Reputation: 944
I have a mat-tab-nav-bar
navigation bar for my website, but the mat-tab-link
blue underlining bar won't chase the active button. It just stays at the first button, and doesn't move. The buttons do turn into active state though in the sense that the background color changes, and they route well to their corresponding pages.
Here's the app.component.ts
:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
navLinks = [
{ path: '', label: 'The Problem' },
{ path: 'the-solution', label: 'The Solution' },
{ path: 'the-game', label: 'The Game' },
{ path: 'probability-calculator', label: 'Probability calculator' },
];
}
And here's the app.component.html
:
<nav mat-tab-nav-bar>
<a mat-tab-link
*ngFor="let link of navLinks"
[routerLink]="link.path"
routerLinkActive #rla="routerLinkActive"
[active]="rla.isActive">
{{link.label}}
</a>
</nav>
<router-outlet></router-outlet>
Here is the app.module.ts
:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { MatTabsModule } from '@angular/material/tabs';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { TheProblemComponent } from './the-problem/the-problem.component';
import { TheSolutionComponent } from './the-solution/the-solution.component';
import { ProbabilityCalculatorComponent } from './probability-calculator/probability-calculator.component';
import { TheGameComponent } from './the-game/the-game.component';
@NgModule({
declarations: [
AppComponent,
TheProblemComponent,
TheSolutionComponent,
ProbabilityCalculatorComponent,
TheGameComponent
],
imports: [
AppRoutingModule,
BrowserModule,
BrowserAnimationsModule,
MatTabsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
What am I missing? Thank you!
EDIT
I edited the app.component.html
like this to find out some more about the link "active" state:
<nav mat-tab-nav-bar>
<a mat-tab-link
*ngFor="let link of navLinks"
[routerLink]="link.path"
routerLinkActive #rla="routerLinkActive"
[active]="rla.isActive">
{{link.label}}
<div style="color: red; margin-left: 10px;">
<span *ngIf="rla.isActive"> Is active!</span>
<span *ngIf="!rla.isActive"> Is not active...</span>
</div>
</a>
</nav>
<router-outlet></router-outlet>
As it turns out, the first link in the menu always remains active (rla.isActive
) - also when I'm navigating to other pages. All other links turn off their active state just fine, and only get activated when they are navigated to. How do I turn off the active state of the first link when navigating to other links?
EDIT 2
Adding app-routing.module.ts
code:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { TheProblemComponent } from './the-problem/the-problem.component';
import { TheSolutionComponent } from './the-solution/the-solution.component';
import { TheGameComponent } from './the-game/the-game.component';
import { ProbabilityCalculatorComponent } from './probability-calculator/probability-calculator.component';
const routes: Routes = [
{ path: '', component: TheProblemComponent },
{ path: 'the-solution', component: TheSolutionComponent },
{ path: 'the-game', component: TheGameComponent },
{ path: 'probability-calculator', component: ProbabilityCalculatorComponent }
];
@NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ]
})
export class AppRoutingModule { }
Upvotes: 22
Views: 47108
Reputation: 25311
I came up with a Directive to achieve the same effect as the other answers without cluttering templates:
@Directive({selector: 'a[routerLinkActive][mat-tab-link]'})
class MatTabRouterLinkActiveDirective {
constructor(routerLinkActive: RouterLinkActive, matTabLink: MatTabLink) {
routerLinkActive.isActiveChange.subscribe(value => matTabLink.active = value);
}
}
With this directive included in your module, all you need is the routerLinkActive
attribute and the directive will take care of the rest:
<a mat-tab-link routerLink="/foo" routerLinkActive>Foo</a>
This gets rid of the #rlaXXX="routerLinkActive" [active]="rlaXXX.isActive"
boilerplate which can get quite repetitive when the tabs are listed directly in the template (as opposed to being generated from *ngFor
or similar).
Upvotes: 0
Reputation: 21690
Using different local variables(#rla1
, #rla2
) worked for me, as i was not using *ngFor
:
<nav mat-tab-nav-bar>
<a mat-tab-link
[routerLink]="['/home/homepage/dashboard/']"
routerLinkActive #rla1="routerLinkActive"
[active]="rla1.isActive">Dashboard
</a>
<a mat-tab-link
[routerLink]="['/home/homepage/reports/']"
routerLinkActive #rla2="routerLinkActive"
[active]="rla2.isActive">Reports
</a>
</nav>
Upvotes: 14
Reputation: 773
It doesn't work for you because every has the same #rla variable
You can do it this way:
<nav mat-tab-nav-bar>
<a mat-tab-link
*ngFor="let link of navLinks"
[routerLink]="link.path"
routerLinkActive #rla="routerLinkActive"
[active]="link.isActive">
{{link.label}}
</a>
</nav>
<router-outlet></router-outlet>
or with {exact:true}
<nav mat-tab-nav-bar>
<a mat-tab-link
*ngFor="let link of navLinks"
[routerLink]="link.path"
routerLinkActive #rla="routerLinkActive"
[routerLinkActiveOptions]="{exact:true}"
[active]="rla.isActive">
{{link.label}}
</a>
</nav>
<router-outlet></router-outlet>
Upvotes: 32
Reputation: 1530
You need to add [routerLinkActiveOptions]="{exact:true}"
to the a
tag.
It becomes
<nav mat-tab-nav-bar>
<a mat-tab-link
*ngFor="let link of navLinks"
[routerLink]="link.path"
routerLinkActive #rla="routerLinkActive"
[routerLinkActiveOptions]="{exact:true}"
[active]="rla.isActive">
{{link.label}}
<div style="color: red; margin-left: 10px;">
<span *ngIf="rla.isActive"> Is active!</span>
<span *ngIf="!rla.isActive"> Is not active...</span>
</div>
</a>
</nav>
<router-outlet></router-outlet>
Upvotes: 6
Reputation: 1751
You can simply follow below code.active
is simply bootstrap class.
<nav mat-tab-nav-bar>
<a mat-tab-link
*ngFor="let link of navLinks"
[routerLink]="['/'+link.path]"
routerLinkActive="active">
{{link.label}}
</a>
</nav>
OR you can do like this below instead of using material design. kindly notice
routerLinkActiveOptions
is used.
<ul class="nav nav-tabs">
<li role="presentation"
routerLinkActive="active"
[routerLinkActiveOptions]="{exact: true}">
<a routerLink="/">The Problem</a>
</li>
<li role="presentation"
routerLinkActive="active">
<a routerLink="/the-solution">The Solution</a>
</li>
<li role="presentation"
routerLinkActive="active">
<a [routerLink]="/the-game">The Game</a>
</li>
....
....
</ul>
Upvotes: 0
Reputation: 26740
You're missing a /
before the link:
<nav mat-tab-nav-bar>
<a mat-tab-link
*ngFor="let link of navLinks"
[routerLink]="['/'+link.path]"
routerLinkActive #rla="routerLinkActive"
[active]="rla.isActive">
{{link.label}}
</a>
</nav>
<router-outlet></router-outlet>
EDIT: The right way here is to set a non-empty path for all routes. You can then use a wildcard with a redirect.
const APP_ROUTES: Route[] = [
{ path: 'path-1', component: OneComponent },
{ path: 'path-2', component: TwoComponent },
{ path: 'path-3', component: ThreeComponent },
{ path: '**', redirectTo: 'path-1' },
]
Upvotes: 9