Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 6 Material: mat-tab-link be selected by underlining bar

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 { }
like image 559
Marcus Edensky Avatar asked May 13 '18 06:05

Marcus Edensky


3 Answers

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>
like image 184
Maciej Sikorski Avatar answered Oct 29 '22 05:10

Maciej Sikorski


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>
like image 27
suhailvs Avatar answered Oct 29 '22 05:10

suhailvs


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' },
]
like image 37
Edric Avatar answered Oct 29 '22 06:10

Edric