В 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>
И убедитесь, что вы не забыли ввести роутер в свой компонент.