ПРИМЕЧАНИЕ. Здесь много разных ответов, и большинство из них были действительны в тот или иной момент. Дело в том, что то, что работает, несколько раз менялось, когда команда Angular меняла свой маршрутизатор. Версия Router 3.0, которая в конечном итоге станет маршрутизатором в Angular, ломает многие из этих решений, но предлагает очень простое собственное решение. Начиная с RC.3, предпочтительным решением является использование [routerLinkActive]
, как показано в этом ответе.
В приложении Angular (текущем в версии 2.0.0-бета.0, когда я пишу это), как вы определяете, какой сейчас активный маршрут?
Я работаю над приложением, которое использует Bootstrap 4, и мне нужен способ пометить навигационные ссылки / кнопки как активные, когда их связанный компонент отображается в теге <router-output>
.
Я понимаю, что могу поддерживать состояние самостоятельно, когда нажата одна из кнопок, но это не будет охватывать случай наличия нескольких путей в одном маршруте (скажем, главное навигационное меню, а также локальное меню в главном компоненте). ) .
Любые предложения или ссылки будут оценены. Спасибо.
28 ответов
С новым Angular router вы можете добавить атрибут [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>
См. X {}} } директива для получения дополнительной информации. (Я в основном понял это методом проб и ошибок.)
ОБНОВЛЕНИЕ: более качественную документацию для директивы routerLinkActive
теперь можно найти здесь. (Спасибо @Victor Hugo Arango A. в комментариях ниже.)
Я искал способ использовать навигацию в стиле Bootstrap в Twitter с 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 ){}
}
Ниже приведены ответы на этот вопрос для всех версий Angular 2 RC, выпущенных до даты:
RC4 и RC3 .
Для применения класса к ссылке или предку ссылки:
<li routerLinkActive="active"><a [routerLink]="['/home']">Home</a></li>
/ home должен быть URL-адресом, а не именем маршрута, поскольку свойство имени больше не существует в объекте маршрута с версии Router v3.
Подробнее о директиве routerLinkActive можно узнать по этой ссылке.
Для применения класса к любому div на основе текущего маршрута:
- Внедрить маршрутизатор в конструктор компонента.
- Пользователь 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>
Ниже приведен метод использования 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;
}
}
Небольшое улучшение ответа @ alex-correia-santos на основе https://github.com / угловой / угловой / тянуть / 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>
А в последней версии 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>
И убедитесь, что вы не забыли ввести роутер в свой компонент.
Как вы определяете, какой сейчас активный маршрут?
ОБНОВЛЕНИЕ: обновлено в соответствии с 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
}
В 2020 году, если вы хотите установить активный класс для элемента, который не имеет [routerLink] - вы можете просто сделать:
<a
(click)="bookmarks()"
[class.active]="router.isActive('/string/path/'+you+'/need', false)" // <== you need this one. second argument 'false' - exact: true/false
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>
bookmarks
</a>
Как упомянуто в одном из комментариев принятого ответа, директива 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
.
Экземпляр класса 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>
Для Angular версии 4+ вам не нужно использовать какое-либо сложное решение. Вы можете просто использовать [routerLinkActive]="'is-active'"
.
Для примера с загрузочной ссылкой 4:
<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>
Использование 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>
И не забудьте включить трубу в зависимости от каналов;)
В 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
в 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
должен быть вставлен в конструктор компонента.
Прямо сейчас я использую RC.4 с начальной загрузкой 4, и этот работает идеально для меня:
<li class="nav-item" routerLinkActive="active" [routerLinkActiveOptions]="{exact:
true}">
<a class="nav-link" [routerLink]="['']">Home</a>
</li>
Это будет работать для URL: / home
Вы можете проверить текущий маршрут, вставив объект Location
в контроллер и проверив path()
, например так:
class MyController {
constructor(private location:Location) {}
... location.path(); ...
}
Вы должны будете убедиться, что импортировали это сначала:
import {Location} from "angular2/router";
Затем вы можете использовать регулярное выражение для сопоставления с путем, который возвращается, чтобы увидеть, какой маршрут активен. Обратите внимание, что класс Location
возвращает нормализованный путь независимо от того, какой LocationStrategy
вы используете. Таким образом, даже если вы используете HashLocationStragegy
, возвращаемые пути все равно будут иметь вид /foo/bar
не #/foo/bar
Я решил проблему, с которой столкнулся в этом ссылка и я выясняю, что есть простое решение для вашего вопроса. Вы можете использовать router-link-active
вместо этого в своих стилях.
@Component({
styles: [`.router-link-active { background-color: red; }`]
})
export class NavComponent {
}
Начать с импорта RouterLinkActive в ваши .ts
импортировать {RouterLinkActive} из '@ angular / router';
Теперь используйте RouterLinkActive в вашем HTML
<span class="" routerLink ="/some_path" routerLinkActive="class_Name">Value</span></a>
Предоставить некоторую CSS для класса "class_Name", так как, когда эта ссылка будет активна / нажата, вы найдете этот класс на промежутке во время проверки.
Просто подумал, что я бы добавил в пример, который не использует машинописный текст:
<input type="hidden" [routerLink]="'home'" routerLinkActive #home="routerLinkActive" />
<section *ngIf="home.isActive"></section>
Переменная routerLinkActive
связана с переменной шаблона и затем используется повторно при необходимости. К сожалению, единственное предостережение в том, что вы не можете иметь все это в элементе <section>
, поскольку #home
необходимо разрешить до , чтобы синтаксический анализатор нажал <section>
.
Вот полный пример добавления активного стиля маршрута в угловой версии 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>
Я использую угловой маршрутизатор ^3.4.7
, и у меня все еще есть проблемы с директивой routerLinkActive
.
Это не работает, если у вас есть несколько ссылок с одним и тем же URL-адресом, и, кажется, не обновляется все время.
Вдохновленный ответом @tomaszbak, я создал небольшой компонент для выполнения этой работы
Допустим, вы хотите добавить 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>
Простое решение для пользователей angular 5 - просто добавьте routerLinkActive
к элементу списка.
Директива routerLinkActive
связана с маршрутом через директиву routerLink
.
Он принимает в качестве входных данных массив классов, которые он добавит к элементу, к которому он присоединен, если его маршрут в данный момент активен, например, так:
<li class="nav-item"
[routerLinkActive]="['active']">
<a class="nav-link"
[routerLink]="['home']">Home
</a>
</li>
Приведенное выше добавит класс active к тегу привязки, если мы в данный момент просматриваем домашний маршрут.
Для маркировки активных маршрутов можно использовать 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
Чистый HTML шаблон будет похож
<a [routerLink]="['/home']" routerLinkActive="active">Home</a>
<a [routerLink]="['/about']" routerLinkActive="active">About us</a>
<a [routerLink]="['/contact']" routerLinkActive="active">Contacts</a>
Начиная с Angular 8, это работает:
<li routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">
<a [routerLink]="['/']">Home</a>
</li>
{ exact: true }
гарантирует, что он соответствует URL.
Решение для 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);
}
Похожие вопросы
Связанные вопросы
Новые вопросы
javascript
По вопросам программирования на ECMAScript (JavaScript / JS) и его различных диалектах / реализациях (кроме ActionScript). Включите все соответствующие теги в свой вопрос; например, [node.js], [jquery], [json] и т. д.