В Angular, как вы определяете активный маршрут?

ПРИМЕЧАНИЕ. Здесь есть много разных ответов, и большинство из них были действительны в тот или иной момент. Дело в том, что то, что работает, несколько раз менялось, когда команда Angular изменила свой маршрутизатор. Версия Router 3.0, которая в конечном итоге будет маршрутизатором в Angular, ломает многие из этих решений, но предлагает очень простое решение. Начиная с RC.3, предпочтительным решением является использование [routerLinkActive], как показано в этом ответе.

В приложении Angular (текущем в версии 2.0.0-beta.0, когда я пишу это), как вы определяете, каков текущий активный маршрут?

Я работаю над приложением, использующим Bootstrap 4, и мне нужен способ отметить ссылки/кнопки навигации как активные, когда их связанный компонент отображается в теге <router-output>.

Я понимаю, что я мог сам поддерживать состояние, когда нажата одна из кнопок, но это не будет охватывать случай наличия нескольких путей в одном и том же маршруте (скажем, главное меню навигации, а также локальное меню в основной компонент).

Любые предложения или ссылки будут оценены. Спасибо.

Ответ 1

С новым угловым маршрутизатором вы можете добавить атрибут [routerLinkActive]="['your-class-name']" ко всем своим ссылкам:

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

Или упрощенный формат без массива, если нужен только один класс:

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

Или еще более простой формат, если нужен только один класс:

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

См. плохо документированную директиву routerLinkActive для получения дополнительной информации. (В основном я понял это методом проб и ошибок.)

ОБНОВЛЕНИЕ: Лучшая документация для директивы routerLinkActive теперь может быть найдена здесь. (Спасибо @Victor Hugo Arango A. в комментариях ниже.)

Ответ 2

Я ответил на это в другом вопросе, но я считаю, что это может иметь отношение и к этому. Здесь ссылка на исходный ответ: Angular 2: Как определить активный маршрут с параметрами?

Я пытаюсь установить класс active, не зная точно, что такое текущее местоположение (используя имя маршрута). Лучшим решением, которое я получил до сих пор, является использование функции isRouteActive, доступной в классе Router.

router.isRouteActive(instruction): Boolean принимает один параметр, который является объектом маршрута Instruction и возвращает true или false, истинна ли эта инструкция или нет для текущего маршрута. Вы можете создать маршрут Instruction, используя Router generate (linkParams: Array). LinkParams следует в том же формате, что и значение, переданное в директиву routerLink (например, router.isRouteActive(router.generate(['/User', { user: user.id }]))).

Вот как RouteConfig может выглядеть как (я немного изменил его, чтобы показать использование параметров):

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

И Вид будет выглядеть так:

<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>

Это было мое предпочтительное решение проблемы до сих пор, это может быть полезно и вам.

Ответ 3

Я решил проблему, с которой я столкнулся в этой ссылке, и я выяснил, что есть простое решение для вашего вопроса. Вы можете использовать router-link-active вместо этого в своих стилях.

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

Ответ 4

Небольшое улучшение ответа @alex-correia-santos на основе 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));
  }
} 

И используйте его следующим образом:

<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>

Ответ 5

Вы можете проверить текущий маршрут, введя объект Location в свой контроллер и проверив path(), например:

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

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

Вам нужно будет сначала его импортировать:

import {Location} from "angular2/router";

Затем вы можете использовать регулярное выражение для соответствия пути, возвращаемому для просмотра того, какой маршрут активен. Обратите внимание, что класс Location возвращает нормализованный путь, независимо от того, какой LocationStrategy вы используете. Поэтому, даже если вы используете HashLocationStragegy, возвращаемые пути будут по-прежнему иметь форму /foo/bar not #/foo/bar

Ответ 6

как вы определяете, каков текущий активный маршрут?

ОБНОВЛЕНИЕ: обновлено согласно Angular2.4.x

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

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

   route.snapshot.component; // active route component

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

подробнее...

Ответ 7

Чтобы отметить активные маршруты routerLinkActive, можно использовать

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

Это также работает с другими элементами, такими как

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

Если частичные соответствия также должны быть отмечены, используйте

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

Насколько я знаю, exact: false будет по умолчанию в RC.4

Ответ 8

Прямо сейчас я использую rc.4 с bootstrap 4, и этот работает идеально для меня:

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

Это будет работать для url:/home

Ответ 9

Ниже приведен метод, использующий RouteData для стилизации элементов menuBar в зависимости от текущего маршрута:

RouteConfig включает данные с вкладкой (текущий маршрут):

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

Кусок макета:

  <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>

Класс:

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;
  }
}

Ответ 10

Здесь приведен полный пример добавления активного стиля маршрута в Angular version 2.0.0-rc.1, который учитывает пустые корневые пути (например, path: '/')

app.component.ts → Маршруты

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>

Ответ 11

Решение для 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);
}

Ответ 12

Router в Angular 2 RC больше не определяет методы isRouteActive и generate.

urlTree - Возвращает текущее дерево url.

createUrlTree(commands: any[], segment?: RouteSegment) - Применяет массив команд к текущему дереву url и создает новое дерево url.

Попробуйте выполнить

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

routeSegment : RouteSegment должно быть введено в конструктор компонента.

Ответ 13

Просто подумал, что добавлю в пример, который не использует никаких typescript:

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

Переменная routerLinkActive привязана к переменной шаблона и затем повторно используется по мере необходимости. К сожалению, единственное предостережение состоит в том, что вы не можете иметь все это в элементе <section>, поскольку #home необходимо разрешить до для удара синтаксического анализатора <section>.

Ответ 14

Использование routerLinkActive хорош в простых случаях, когда есть ссылка, и вы хотите применить некоторые классы. Но в более сложных случаях, когда у вас может не быть routerLink или где вам нужно что-то еще, вы можете создать и использовать 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);
    }
}

то

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

и не забудьте включить трубку в зависимости от труб;)

Ответ 15

Другой способ обхода проблемы. Гораздо проще в Angular Router V3 Alpha. путем ввода маршрутизатора

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

export class AppComponent{

    constructor(private router : Router){}

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

Использование

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

Ответ 16

В Angular2 RC2 вы можете использовать эту простую реализацию

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

это добавит класс active к элементу с соответствующим URL-адресом, подробнее об этом здесь

Ответ 17

Ниже приведены ответы на этот вопрос для всех версий версий Angular 2 RC, выпущенных до даты:

RC4 и RC3:

Для применения класса к ссылке или предку ссылки:

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

/home должен быть URL, а не имя маршрута, поскольку свойство имени больше не существует в объекте маршрута с маршрутизатора v3.

Подробнее о директиве routerLinkActive на link.

Для применения класса к любому div на основе текущего маршрута:

  • Inject Router в конструктор компонента.
  • Пользователь router.url для сравнения.

например

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

RC2 и RC1:

Используйте комбинацию router.isRouteActive и class. *. например, применять активный класс на основе Home Route.

Имя и URL могут быть переданы в router.generate.

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

Ответ 18

Для Angular версии 4+ вам не нужно использовать какое-либо сложное решение. Вы можете просто использовать [routerLinkActive]="'is-active'".

Для примера с 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>

Ответ 19

Экземпляр класса Router на самом деле является Observable и он возвращает текущий путь каждый раз, когда он изменяется. Вот как я это делаю:

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;
 } 
}

И затем в моем HTML:

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

Ответ 20

Как упоминалось в одном из комментариев принятого ответа, директива routerLinkActive также может быть применена к контейнеру фактического тега <a>.

Итак, например с вкладками Twitter Bootstrap, где активный класс должен быть применен к тегу <li>, который содержит ссылку:

<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>

Довольно аккуратно! Я полагаю, что директива проверяет содержимое тега и ищет тег <a> с директивой routerLink.

Ответ 21

Я искал способ использования стиля загрузки Bootstrap в Twitter с помощью Angular2, но не удалось получить класс active, примененный к родительскому элементу выбранной ссылки. Найдено, что решение @alex-rectia-santos отлично работает!

Компонент, содержащий ваши вкладки, должен импортировать маршрутизатор и определить его в своем конструкторе, прежде чем вы сможете сделать необходимые вызовы.

Вот упрощенная версия моей реализации...

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 ){}
}

Ответ 22

скажем, вы хотите добавить CSS в мое активное состояние/вкладку. Используйте routerLinkActive, чтобы активировать вашу маршрутную ссылку.

note: "active" - это мое имя класса здесь

<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>

Ответ 23

Простое решение для angular 5 пользователей, просто добавьте routerLinkActive в элемент списка.

Директива

A routerLinkActive связана с маршрутом через директиву routerLink.

В качестве ввода вводится массив классов, который он добавит к элементу, к которому он присоединен, если его маршрут в настоящее время активен, например:

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

Вышеупомянутый класс добавит класс активного к тегу привязки, если мы сейчас просматриваем домашний маршрут.

Demo

Ответ 24

Я использую angular router ^3.4.7, и у меня все еще возникают проблемы с директивой routerLinkActive.

Он не работает, если у вас есть несколько ссылок с тем же URL-адресом, и он, кажется, не обновляется все время.

Вдохновленный ответом @tomaszbak, я создал маленький компонент для выполнения задания

Ответ 25

Чистый HTML шаблон будет похож

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

Ответ 26

начать с импорта RouterLinkActive в ваши .ts

импортировать {RouterLinkActive} из '@angular/router';

Теперь используйте RouterLinkActive в вашем HTML

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

предоставить некоторую CSS для класса "class_Name", так как, когда эта ссылка будет активна/нажата, вы найдете этот класс на промежутке во время проверки.

Ответ 27

Начиная с Angular 8, это работает:

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

{ exact: true } гарантирует, что оно соответствует URL.

Ответ 28

А в последней версии angular вы можете просто проверить router.isActive(routeNameAsString). Например, см. Пример ниже:

 <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>

И убедитесь, что вы не забыли ввести роутер в свой компонент.