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

Примечание: есть много разных ответов здесь, и большинство из них были действительны в то или иное время. Дело в том, что то, что работает, несколько раз менялось, поскольку команда Angular изменила свой маршрутизатор. Версия маршрутизатора 3.0, которая в конечном итоге будет на маршрутизатор в угловых перерывах многие из этих решений, но предлагает очень простое решение самостоятельно. По состоянию на RC.3, предпочтительным решением является использование [routerLinkActive] как показано в этот ответ.

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

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

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

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

25 ответов


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

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

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

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

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

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


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

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

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


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

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

небольшое улучшение для ответа @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>

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

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

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

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

import {Location} from "angular2/router";

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


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

UPDATE: Обновлено в соответствии с 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
}

Посмотреть больше...


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

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

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

app.деталь.ТС -> маршруты

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.деталь.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>

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

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

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

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


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

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

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

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

если частичные совпадения также следует отметить use

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

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


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 необходимо ввести в конструктор компонента.


экземпляр класса маршрутизатора на самом деле является наблюдаемым и возвращает текущий путь каждый раз, когда он изменяется. Вот как я это делаю:--3-->

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>

Другое Решение. Гораздо проще в 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>

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

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

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


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

RC4 и RC3 :

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

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

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

больше о директиве routerLinkActive на этом ссылке.

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

  • внедрить маршрутизатор в конструктор компонента.
  • маршрутизатор.URL для сравнения.

Эл.г

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

RC2 и rc1 и:

используйте комбинацию маршрутизатора.isRouteActive и класс.*. e.g применение активного класса на основе домашнего маршрута.

имя и url-адрес могут быть переданы в обращать в бегство.генерировать.

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

используя routerLinkActive хорош в простых случаях, когда есть ссылка и вы хотите применить некоторые классы. Но в более сложных случаях, когда у вас может не быть routerLink или вам нужно что-то еще, вы можете создать и использовать труба:

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

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


как уже упоминалось в одном из комментариев принятого ответа,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> тега


для угловой версии 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>

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

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

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


Я искал способ использовать Twitter Bootstrap style nav с Angular2, но не смог получить active класс, примененный к родительскому элементу выбранной ссылки. Обнаружил, что решение @alex-correia-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 ){}
}

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

Примечание: "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>

Я использую угловой маршрутизатор ^3.4.7 и у меня все еще есть проблемы с


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

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


чистый html шаблон быть как

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