ПРИМЕЧАНИЕ. Здесь есть много разных ответов, и большинство из них были действительны в тот или иной момент. Дело в том, что то, что работает, несколько раз менялось, когда команда Angular изменила свой маршрутизатор. Версия Router 3.0, которая в конечном итоге будет маршрутизатором в Angular, ломает многие из этих решений, но предлагает очень простое решение. Начиная с RC.3, предпочтительным решением является использование [routerLinkActive]
, как показано в этом ответе.
В приложении Angular (текущем в версии 2.0.0-beta.0, когда я пишу это), как вы определяете, каков текущий активный маршрут?
Я работаю над приложением, использующим Bootstrap 4, и мне нужен способ отметить ссылки/кнопки навигации как активные, когда их связанный компонент отображается в теге <router-output>
.
Я понимаю, что я мог сам поддерживать состояние, когда нажата одна из кнопок, но это не будет охватывать случай наличия нескольких путей в одном и том же маршруте (скажем, главное меню навигации, а также локальное меню в основной компонент).
Любые предложения или ссылки будут оценены. Спасибо.
С помощью нового Angular router вы можете добавить атрибут [routerLinkActive]="['your-class-name']"
ко всем вашим ссылкам:
<a [routerLink]="['/home']" [routerLinkActive]="['is-active']">Home</a>
Или упрощенный формат без массива, если требуется только один класс:
<a [routerLink]="['/home']" [routerLinkActive]="'is-active'">Home</a>
Подробную информацию см. в плохо документированной директиве routerLinkActive
. (Я в основном понял это путем проб и ошибок.)
UPDATE: теперь можно найти лучшую документацию для директивы routerLinkActive
здесь. (Спасибо @Victor Hugo Arango A. в комментариях ниже.)
Я ответил на это в другом вопросе, но я считаю, что это может иметь отношение и к этому. Здесь ссылка на исходный ответ: 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>
Это было мое предпочтительное решение проблемы до сих пор, это может быть полезно и вам.
router.isRouteActive('Home')
.
Я решил проблему, с которой я столкнулся в этой ссылке, и я выяснил, что есть простое решение для вашего вопроса. Вы можете использовать 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>
styles : [
компонентов styles : [
.active {background-color: aliceblue; } ]
. +1 это работает
Вы можете проверить текущий маршрут, введя объект Location
в свой контроллер и проверив path()
, например:
class MyController {
constructor(private location:Location) {}
... location.path(); ...
}
Вам нужно будет сначала его импортировать:
import {Location} from "angular2/router";
Затем вы можете использовать регулярное выражение для соответствия пути, возвращаемому для просмотра того, какой маршрут активен. Обратите внимание, что класс Location
возвращает нормализованный путь, независимо от того, какой LocationStrategy
вы используете. Поэтому, даже если вы используете HashLocationStragegy
, возвращаемые пути будут по-прежнему иметь форму /foo/bar
not #/foo/bar
как вы определяете, каков текущий активный маршрут?
ОБНОВЛЕНИЕ: обновлено согласно 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
}
Решение для 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);
}
Чтобы отметить активные маршруты 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
Здесь приведен полный пример добавления активного стиля маршрута в 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>
Ниже приведен метод, использующий 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;
}
}
Прямо сейчас я использую rc.4 с bootstrap 4, и этот работает идеально для меня:
<li class="nav-item" routerLinkActive="active" [routerLinkActiveOptions]="{exact:
true}">
<a class="nav-link" [routerLink]="['']">Home</a>
</li>
Это будет работать для url:/home
/home/whatever
?
exact
означает, что этот маршрут будет иметь то же имя. И это необходимо, если вы планируете использовать его с такими инструментами, как Twitter bootstrap. Он уже обрабатывает активное состояние ссылки и без exact
параметра не будет работать. (не уверен, как это работает в ядре, я попробовал, и это работает для меня)
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
должно быть введено в конструктор компонента.
Как упоминалось в одном из комментариев принятого ответа, директива 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
.
Ниже приведены ответы на этот вопрос для всех версий версий Angular 2 RC, выпущенных до даты:
RC4 и RC3:
Для применения класса к ссылке или предку ссылки:
<li routerLinkActive="active"><a [routerLink]="['/home']">Home</a></li>
/home должен быть URL, а не имя маршрута, поскольку свойство имени больше не существует в объекте маршрута с маршрутизатора v3.
Подробнее о директиве routerLinkActive на link.
Для применения класса к любому div на основе текущего маршрута:
например
<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>
В Angular2 RC2 вы можете использовать эту простую реализацию
<a [routerLink]="['/dashboard']" routerLinkActive="active">Dashboard</a>
это добавит класс active
к элементу с соответствующим URL-адресом, подробнее об этом здесь
Другой способ обхода проблемы. Гораздо проще в 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>
Экземпляр класса 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>
Использование 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>
и не забудьте включить трубку в зависимости от труб;)
containsTree
дерево?
Для 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>
скажем, вы хотите добавить 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>
Я искал способ использования стиля загрузки 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 ){}
}
Простое решение для angular 5 пользователей, просто добавьте routerLinkActive
в элемент списка.
A routerLinkActive
связана с маршрутом через директиву routerLink
.
В качестве ввода вводится массив классов, который он добавит к элементу, к которому он присоединен, если его маршрут в настоящее время активен, например:
<li class="nav-item"
[routerLinkActive]="['active']">
<a class="nav-link"
[routerLink]="['home']">Home
</a>
</li>
Вышеупомянутый класс добавит класс активного к тегу привязки, если мы сейчас просматриваем домашний маршрут.
Просто подумал, что добавлю в пример, который не использует никаких typescript:
<input type="hidden" [routerLink]="'home'" routerLinkActive #home="routerLinkActive" />
<section *ngIf="home.isActive"></section>
Переменная routerLinkActive
привязана к переменной шаблона и затем повторно используется по мере необходимости. К сожалению, единственное предостережение состоит в том, что вы не можете иметь все это в элементе <section>
, поскольку #home
необходимо разрешить до для удара синтаксического анализатора <section>
.
Я использую angular router ^3.4.7
, и у меня все еще возникают проблемы с директивой routerLinkActive
.
Он не работает, если у вас есть несколько ссылок с тем же URL-адресом, и он, кажется, не обновляется все время.
Вдохновленный ответом @tomaszbak, я создал маленький компонент для выполнения задания
is-active
будет добавлен как класс только к активной ссылке.@input
для параметров, ноexact: false
активирует класс всякий раз, когда братья и сестры текущего маршрута также активны.