web-dev-qa-db-fra.com

Dans Angular, comment déterminez-vous l'itinéraire actif?

NOTE: _ ​​Il y a beaucoup de réponses différentes ici, et la plupart ont été valables à un moment ou à un autre. Le fait est que ce qui fonctionne a changé plusieurs fois, l'équipe angulaire ayant changé de routeur. La version 3.0 qui sera finalement le routeur dans Angular casse beaucoup de ces solutions, mais offre une solution très simple. A partir de RC.3, la solution recommandée consiste à utiliser [routerLinkActive] comme indiqué dans cette réponse. .

Dans une application Angular (actuelle dans la version 2.0.0-beta.0 au moment où j'écris ceci), comment déterminez-vous quel est l'itinéraire actuellement actif?

Je travaille sur une application qui utilise Bootstrap 4 et j'ai besoin d'un moyen de marquer les liens/boutons de navigation comme étant actifs lorsque leur composant associé est affiché dans une balise <router-output>.

Je me rends compte que je pourrais conserver moi-même l'état lorsque l'un des boutons est cliqué, mais cela ne couvrirait pas le cas de plusieurs chemins dans le même itinéraire (disons un menu de navigation principal ainsi qu'un menu local dans le composant principal ).

Toute suggestion ou lien serait apprécié. Merci.

232
Michael Oryl

Avec le nouveau routeur Angular , vous pouvez ajouter un attribut [routerLinkActive]="['your-class-name']" à tous vos liens:

<a [routerLink]="['/home']" [routerLinkActive]="['is-active']">Home</a>

Ou le format simplifié non-tableau si une seule classe est nécessaire:

<a [routerLink]="['/home']" [routerLinkActive]="'is-active'">Home</a>

Voir la directive mal documentée routerLinkActive pour plus d'informations. (J'ai surtout compris cela par essais et erreurs.)

UPDATE: Il est maintenant possible de trouver une meilleure documentation pour la directive routerLinkActivehere . (Merci à @Victor Hugo Arango A. dans les commentaires ci-dessous.)

283
jessepinho

J'ai répondu à cela dans une autre question, mais je pense que cela pourrait également s'appliquer à celle-ci. Voici un lien vers la réponse originale: Angular 2: Comment déterminer un itinéraire actif avec des paramètres?

J'ai essayé de régler le actif classe sans avoir à savoir exactement quelle est la position actuelle (en utilisant le nom de la route). Pour l'instant, la meilleure solution consiste à utiliser la fonction isRouteActive disponible dans la classe Router.

router.isRouteActive(instruction): Boolean prend un paramètre qui est un objet route Instruction et renvoie true ou false si cette instruction est vraie ou non pour la route en cours. Vous pouvez générer une route Instruction en utilisant Router 's generate (linkParams: Array) . LinkParams suit exactement le même format qu’une valeur passée dans une directive routerLink (par exemple, router.isRouteActive(router.generate(['/User', { user: user.id }]))).

Voici comment RouteConfig pourrait ressembler (Je l'ai un peu modifié pour montrer l'utilisation de params):

@RouteConfig([
  { path: '/', component: HomePage, name: 'Home' },
  { path: '/signin', component: SignInPage, name: 'SignIn' },
  { path: '/profile/:username/feed', component: FeedPage, name: 'ProfileFeed' },
])

Et le Vue ressemblerait à ceci:

<li [class.active]="router.isRouteActive(router.generate(['/Home']))">
   <a [routerLink]="['/Home']">Home</a>
</li>
<li [class.active]="router.isRouteActive(router.generate(['/SignIn']))">
   <a [routerLink]="['/SignIn']">Sign In</a>
</li>
<li [class.active]="router.isRouteActive(router.generate(['/ProfileFeed', { username: user.username }]))">
    <a [routerLink]="['/ProfileFeed', { username: user.username }]">Feed</a>
</li>

Cela a été ma solution préférée pour le problème jusqu'à présent, cela pourrait également vous être utile.

65
Alex Santos

J'ai résolu un problème rencontré dans ce link et je découvre qu'il existe une solution simple à votre question. Vous pouvez utiliser router-link-active à la place dans vos styles.

@Component({
   styles: [`.router-link-active { background-color: red; }`]
})
export class NavComponent {
}
33
Quy Tang

Petite amélioration de la réponse @ alex-correia-santos basée sur https://github.com/angular/angular/pull/6407#issuecomment-190179875

import {Router, RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
// ...
export class App {
  constructor(private router: Router) {
  }

  // ...

  isActive(instruction: any[]): boolean {
    return this.router.isRouteActive(this.router.generate(instruction));
  }
} 

Et utilisez-le comme ceci:

<ul class="nav navbar-nav">
    <li [class.active]="isActive(['Home'])">
        <a [routerLink]="['Home']">Home</a>
    </li>
    <li [class.active]="isActive(['About'])">
        <a [routerLink]="['About']">About</a>
    </li>
</ul>
29
tomaszbak

Vous pouvez vérifier l'itinéraire actuel en injectant l'objet Location dans votre contrôleur et en vérifiant le path(), comme suit:

class MyController {
    constructor(private location:Location) {}

    ...  location.path(); ...
}

Vous devrez d'abord l'importer:

import {Location} from "angular2/router";

Vous pouvez ensuite utiliser une expression régulière pour établir une correspondance avec le chemin renvoyé afin de voir quel itinéraire est actif. Notez que la classe Location renvoie un chemin normalisé quel que soit le LocationStrategy que vous utilisez. Ainsi, même si vous utilisez la variable HashLocationStragegy, les chemins renvoyés seront toujours de la forme /foo/bar pas #/foo/bar

28
Jason Teplitz

comment déterminez-vous l'itinéraire actuel?

UPDATE: mis à jour selon Angular2.4.x

constructor(route: ActivatedRoute) {
   route.snapshot.params; // active route's params

   route.snapshot.data; // active route's resolved data

   route.snapshot.component; // active route's component

   route.snapshot.queryParams // The query parameters shared by all the routes
}

voir plus ...

16
Ankit Singh

Pour marquer des itinéraires actifs, routerLinkActive peut être utilisé

<a [routerLink]="/user" routerLinkActive="some class list">User</a>

Cela fonctionne également sur d'autres éléments comme

<div routerLinkActive="some class list">
  <a [routerLink]="/user">User</a>
</div>

Si les correspondances partielles doivent également être marquées, utilisez

routerLinkActive="some class list" [routerLinkActiveOptions]="{ exact: false }"

Autant que je sache, exact: false va être la valeur par défaut dans RC.4

8
Günter Zöchbauer

En ce moment, j'utilise rc.4 avec bootstrap 4 et celui-ci fonctionne parfaitement pour moi:

 <li class="nav-item" routerLinkActive="active" [routerLinkActiveOptions]="{exact:
true}">
    <a class="nav-link" [routerLink]="['']">Home</a>
</li>

Cela fonctionnera pour url:/home

7
Artem Zinoviev

Ci-dessous, la méthode utilisant RouteData pour styler les éléments de menuBar en fonction de l'itinéraire actuel:

RouteConfig inclut des données avec onglet (itinéraire actuel):

@RouteConfig([
  {
    path: '/home',    name: 'Home',    component: HomeComponent,
    data: {activeTab: 'home'},  useAsDefault: true
  }, {
    path: '/jobs',    name: 'Jobs',    data: {activeTab: 'jobs'},
    component: JobsComponent
  }
])

Un morceau de mise en page:

  <li role="presentation" [ngClass]="{active: isActive('home')}">
    <a [routerLink]="['Home']">Home</a>
  </li>
  <li role="presentation" [ngClass]="{active: isActive('jobs')}">
    <a [routerLink]="['Jobs']">Jobs</a>
  </li>

Classe:

export class MainMenuComponent {
  router: Router;

  constructor(data: Router) {
    this.router = data;
  }

  isActive(tab): boolean {
    if (this.router.currentInstruction && this.router.currentInstruction.component.routeData) {
      return tab == this.router.currentInstruction.component.routeData.data['activeTab'];
    }
    return false;
  }
}
6
Ivan

Voici un exemple complet d'ajout de style de route active dans la version angulaire 2.0.0-rc.1 qui prend en compte les chemins racine nuls (par exemple path: '/')

app.component.ts -> Itinéraires

import { Component, OnInit } from '@angular/core';
import { Routes, Router, ROUTER_DIRECTIVES } from '@angular/router';
import { LoginPage, AddCandidatePage } from './export';
import {UserService} from './SERVICES/user.service';

@Component({
  moduleId: 'app/',
  selector: 'my-app',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css'],
  providers: [UserService],
  directives: [ROUTER_DIRECTIVES]
})

@Routes([
  { path: '/', component: AddCandidatePage },
  { path: 'Login', component: LoginPage }
])
export class AppComponent  { //implements OnInit

  constructor(private router: Router){}

  routeIsActive(routePath: string) {
     let currentRoute = this.router.urlTree.firstChild(this.router.urlTree.root);
     // e.g. 'Login' or null if route is '/'
     let segment = currentRoute == null ? '/' : currentRoute.segment;
     return  segment == routePath;
  }
}

app.component.html

<ul>
  <li [class.active]="routeIsActive('Login')"><a [routerLink]="['Login']" >Login</a></li>
  <li [class.active]="routeIsActive('/')"><a [routerLink]="['/']" >AddCandidate</a></li>
</ul>
<route-outlet></router-outlet>
6
Levi Fuller

Solution pour Angular2 RC 4:

import {containsTree} from '@angular/router/src/url_tree';
import {Router} from '@angular/router';

export function isRouteActive(router: Router, route: string) {
   const currentUrlTree = router.parseUrl(router.url);
   const routeUrlTree = router.createUrlTree([route]);
   return containsTree(currentUrlTree, routeUrlTree, true);
}
6
lukaville

Router in Angular 2 RC ne définit plus les méthodes isRouteActive et generate.

urlTree - Retourne l’arborescence actuelle.

createUrlTree(commands: any[], segment?: RouteSegment) - Applique un tableau de commandes à l’arborescence actuelle et crée une nouvelle arborescence.

Essayez de suivre

<li 
[class.active]=
"router.urlTree.contains(router.createUrlTree(['/SignIn', this.routeSegment]))">

notice, routeSegment : RouteSegment doit être injecté dans le constructeur du composant. 

5
tchelidze

Utiliser routerLinkActive est bon dans les cas simples, quand il y a un lien et que vous voulez appliquer des classes. Mais dans les cas plus complexes où vous n’avez peut-être pas de routeur (ou un lien supplémentaire), vous pouvez créer et utiliser un pipe :

@Pipe({
    name: "isRouteActive",
    pure: false
})
export class IsRouteActivePipe implements PipeTransform {

    constructor(private router: Router,
                private activatedRoute: ActivatedRoute) {
    }

    transform(route: any[], options?: { queryParams?: any[], fragment?: any, exact?: boolean }) {
        if (!options) options = {};
        if (options.exact === undefined) options.exact = true;

        const currentUrlTree = this.router.parseUrl(this.router.url);
        const urlTree = this.router.createUrlTree(route, {
            relativeTo: this.activatedRoute,
            queryParams: options.queryParams,
            fragment: options.fragment
        });
        return containsTree(currentUrlTree, urlTree, options.exact);
    }
}

puis:

<div *ngIf="['/some-route'] | isRouteActive">...</div>

et n'oubliez pas d'inclure pipe dans les dépendances de pipes;)

4
pleerock

Une instance de la classe Router est en réalité un observable et renvoie le chemin actuel à chaque changement. Voici comment je le fais:

export class AppComponent implements OnInit { 

currentUrl : string;

constructor(private _router : Router){
    this.currentUrl = ''
}

ngOnInit() {
    this._router.subscribe(
        currentUrl => this.currentUrl = currentUrl,
        error => console.log(error)
    );
}

isCurrentRoute(route : string) : boolean {
    return this.currentUrl === route;
 } 
}

Et puis dans mon HTML:

<a [routerLink]="['Contact']" class="item" [class.active]="isCurrentRoute('contact')">Contact</a>
4
Anees Dhansey

Une autre solution de contournement. Beaucoup plus facile dans Angular Router V3 Alpha. en injectant un routeur

import {Router} from "@angular/router";

export class AppComponent{

    constructor(private router : Router){}

    routeIsActive(routePath: string) {
        return this.router.url == routePath;
    }
}

usage

<div *ngIf="routeIsActive('/')"> My content </div>
4
shakee93

Dans Angular2 RC2, vous pouvez utiliser cette implémentation simple

<a [routerLink]="['/dashboard']" routerLinkActive="active">Dashboard</a>

cela ajoutera la classe active à l'élément avec l'URL correspondante, en savoir plus à ce sujet ici

4
Khaled Al-Ansari

Vous trouverez ci-dessous les réponses à cette question pour toutes les versions des versions d'Angular 2 RC publiées jusqu'à ce jour:

RC4 et RC3:

Pour appliquer une classe à un lien ou un ancêtre de lien: 

<li routerLinkActive="active"><a [routerLink]="['/home']">Home</a></li>

/home doit être l'URL et non le nom de la route car la propriété name n'existe plus sur l'objet Route à partir du routeur v3.

Plus d'informations sur la directive routerLinkActive à cette lien .

Pour appliquer une classe à une division en fonction de l’itinéraire actuel: 

  • Injectez le routeur dans le constructeur du composant. 
  • Routeur.url utilisateur pour la comparaison. 

par exemple

<nav [class.transparent]="router.url==('/home')">
</nav>

RC2 et RC1:

Utilisez une combinaison de router.isRouteActive et class. *. par exemple, appliquer une classe active basée sur l'itinéraire local. 

Nom et URL peuvent être tous deux passés dans router.generate.

 <li [class.active]="router.isRouteActive(router.generate(['Home']))">
    <a [routerLink]="['Home']" >Home</a>
</li>
4
Inderdeep Singh

Pour Angular version 4+, vous n’avez besoin d’aucune solution complexe. Vous pouvez simplement utiliser [routerLinkActive]="'is-active'".

Pour un exemple avec bootstrap 4 nav link:

    <ul class="navbar-nav mr-auto">
      <li class="nav-item" routerLinkActive="active">
        <a class="nav-link" routerLink="/home">Home</a>
      </li>
      <li class="nav-item" routerLinkActive="active">
        <a class="nav-link" routerLink="/about-us">About Us</a>
      </li>
      <li class="nav-item" routerLinkActive="active">
        <a class="nav-link " routerLink="/contact-us">Contact</a>
      </li>
    </ul>
4
asmmahmud

Je pensais juste que j'ajouterais un exemple qui n'utilise aucun TypeScript:

<input type="hidden" [routerLink]="'home'" routerLinkActive #home="routerLinkActive" />
<section *ngIf="home.isActive"></section>

La variable routerLinkActive est liée à une variable de modèle, puis réutilisée selon les besoins. Malheureusement, le seul inconvénient est que vous ne pouvez pas avoir tout cela sur l'élément <section> car #home doit être résolu avant à l'analyseur qui clique sur <section>.

3
Zze

Comme indiqué dans l'un des commentaires de la réponse acceptée, la directive routerLinkActive peut également être appliquée à un conteneur de la balise <a> réelle. 

Ainsi par exemple avec les onglets Twitter Bootstrap où la classe active doit être appliquée à la balise <li> qui contient le lien:

<ul class="nav nav-tabs">
    <li role="presentation" routerLinkActive="active">
        <a routerLink="./location">Location</a>
    </li>
    <li role="presentation" routerLinkActive="active">
        <a routerLink="./execution">Execution</a>
    </li>
</ul>

Génial ! Je suppose que la directive inspecte le contenu de la balise et recherche une balise <a> avec la directive routerLink.

3
Pierre Henry

La solution simple pour les utilisateurs angulaires 5 consiste simplement à ajouter routerLinkActive à l’élément de la liste. 

Une directive routerLinkActive est associée à une route via une directive routerLink.

Il prend en entrée un tableau de classes qu’il ajoutera à l’élément auquel il est attaché si sa route est actuellement active, comme ceci:

<li class="nav-item"
    [routerLinkActive]="['active']">
  <a class="nav-link"
     [routerLink]="['home']">Home
  </a>
</li>

Ce qui précède ajoutera une classe d'actif à la balise d'ancrage si nous visualisons actuellement l'itinéraire de départ.

 Demo

1
Prasanth Jaya

Je cherchais un moyen d'utiliser une navigation de style Twitter Bootstrap avec Angular2, mais je ne pouvais pas appliquer la classe active à l'élément parent du lien sélectionné. Constaté que la solution de @ alex-correia-santos fonctionne parfaitement!

Le composant contenant vos onglets doit importer le routeur et le définir dans son constructeur avant de pouvoir effectuer les appels nécessaires.

Voici une version simplifiée de mon implémentation ...

import {Component} from 'angular2/core';
import {Router, RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
import {HomeComponent} from './home.component';
import {LoginComponent} from './login.component';
import {FeedComponent} from './feed.component';

@Component({
  selector: 'my-app',
  template: `
    <ul class="nav nav-tabs">
      <li [class.active]="_r.isRouteActive(_r.generate(['Home']))">
        <a [routerLink]="['Home']">Home</a>
      </li>
      <li [class.active]="_r.isRouteActive(_r.generate(['Login']))">
        <a [routerLink]="['Login']">Sign In</a>
      </li>
      <li [class.active]="_r.isRouteActive(_r.generate(['Feed']))">
        <a [routerLink]="['Feed']">Feed</a>
      </li>
    </ul>`,
  styleUrls: ['app/app.component.css'],
  directives: [ROUTER_DIRECTIVES]
})
@RouteConfig([
  { path:'/', component:HomeComponent, name:'Home', useAsDefault:true },
  { path:'/login', component:LoginComponent, name:'Login' },
  { path:'/feed', component:FeedComponent, name:'Feed' }
])
export class AppComponent {
  title = 'My App';
  constructor( private _r:Router ){}
}
1
Ben Thielker

supposons que vous souhaitiez ajouter du CSS à mon état/onglet actif. Utilisez routerLinkActive pour activer votre lien de routage.

note: 'actif' est le nom de ma classe ici

<style>
   .active{
       color:blue;
     }
</style>

  <a routerLink="/home" [routerLinkActive]="['active']">Home</a>
  <a routerLink="/about" [routerLinkActive]="['active']">About</a>
  <a routerLink="/contact" [routerLinkActive]="['active']">Contact</a>
1
UniCoder

À partir de Angular 8, cela fonctionne:

<li routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">
    <a [routerLink]="['/']">Home</a>
</li>

{ exact: true } s'assure qu'il correspond à l'URL.

0
John Kennedy

commencez par importer RouterLinkActive dans votre fichier .ts

importer {RouterLinkActive} depuis '@ angular/router';

Maintenant, utilisez RouterLinkActive dans votre code HTML

<span class="" routerLink ="/some_path" routerLinkActive="class_Name">Value</span></a>

fournissez quelques css à la classe "nom_classe", car lorsque ce lien sera actif/cliqué, vous trouverez cette classe sur la durée de l'inspection.

0
T. Shashwat

Modèle html pur soit comme

 <a [routerLink]="['/home']" routerLinkActive="active">Home</a>
 <a [routerLink]="['/about']" routerLinkActive="active">About us</a>
 <a [routerLink]="['/contact']" routerLinkActive="active">Contacts</a>
0
Bellash

Et dans la dernière version de angular, vous pouvez simplement vérifier router.isActive(routeNameAsString). Par exemple, voir l'exemple ci-dessous:

 <div class="collapse navbar-collapse" id="navbarNav">
    <ul class="navbar-nav">
      <li class="nav-item" [class.active] = "router.isActive('/dashboard')">
        <a class="nav-link" href="#">داشبورد <span class="sr-only">(current)</span></a>
      </li>
      <li class="nav-item" [class.active] = "router.isActive(route.path)" *ngFor="let route of (routes$ | async)">
        <a class="nav-link" href="javascript:void(0)" *ngIf="route.childRoutes && route.childRoutes.length > 0"
          [matMenuTriggerFor]="menu">{{route.name}}</a>
        <a class="nav-link" href="{{route.path}}"
          *ngIf="!route.childRoutes || route.childRoutes.length === 0">{{route.name}}</a>
        <mat-menu #menu="matMenu">
          <span *ngIf="route.childRoutes && route.childRoutes.length > 0">
            <a *ngFor="let child of route.childRoutes" class="nav-link" href="{{route.path + child.path}}"
              mat-menu-item>{{child.name}}</a>
          </span>
        </mat-menu>
      </li>
    </ul>
    <span class="navbar-text mr-auto">
      <small>سلام</small> {{ (currentUser$ | async) ? (currentUser$ | async).firstName : 'کاربر' }}
      {{ (currentUser$ | async) ? (currentUser$ | async).lastName : 'میهمان' }}
    </span>
  </div>

Et assurez-vous de ne pas oublier d’injecter un routeur dans votre composant.

0
ConductedClever

J'utilise un routeur angulaire ^3.4.7 et j'ai toujours des problèmes avec la directive routerLinkActive.

Cela ne fonctionne pas si vous avez plusieurs liens avec la même URL, plus cela ne semble pas rafraîchir tout le temps.

Inspiré par @tomaszbak answer, j'ai créé un petit composant pour faire le travail

0
RPDeshaies