Angular2: сделать маршруты маршрута нечувствительными к регистру
У меня есть следующая конфигурация маршрутизации.
@RouteConfig([
{
path: '/home',
name: 'Homepage',
component: HomepageComponent,
useAsDefault: true
}
)
export class AppComponent {
}
всякий раз, когда браузер указывает на /home
, этот маршрут работает, но не для /home
или любых других вариантов. Как я могу заставить маршрутизатор маршрутизировать компонент, не заботясь об этом случае.
спасибо
Ответы
Ответ 1
Вот что я сделал.
import { DefaultUrlSerializer, UrlTree } from '@angular/router';
export class LowerCaseUrlSerializer extends DefaultUrlSerializer {
parse(url: string): UrlTree {
return super.parse(url.toLowerCase());
}
}
и
@NgModule({
imports: [
...
],
declarations: [AppComponent],
providers: [
{
provide: UrlSerializer,
useClass: LowerCaseUrlSerializer
}
],
bootstrap: [AppComponent]
})
Ответ 2
Обновление
Это еще не попало в новый маршрутизатор
оригинальный
Регуляторы регулярных выражений были введены недавно. Это может помочь в вашем случае использования.
См. https://github.com/angular/angular/pull/7332/files
И этот Plunker от Brandon Roberts
@RouteConfig([
{ name : 'Test',
//path : '/test',
regex: '^(.+)/(.+)$',
serializer: (params) => new GeneratedUrl(`/${params.a}/${params.b}`, {c: params.c}),
component: Test
// useAsDefault: true
}
])
Ответ 3
Я сделал это в своем app.component.ts:
export class AppComponent implements OnInit {
constructor(private _route: Router) { }
public ngOnInit() {
this._route.events.subscribe(event => {
if (event instanceof NavigationStart) {
let url = (<NavigationStart>event).url;
if (url !== url.toLowerCase()) {
this._route.navigateByUrl((<NavigationStart>event).url.toLowerCase());
}
}
});
}
}
и это необходимо для маршрутизатора-ссылки, чтобы сделать его активным при выборе:
<a routerLink="/heroes" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: false }">Heroes</a>
Ответ 4
Примечание. В Angular 4.x
работает следующее:
Я просто использую функцию-сопряжение:
import { RouterModule, UrlSegment, UrlSegmentGroup, Route } from '@angular/router';
function CaseInsensitiveMatcher(url: string) {
url = url.toLowerCase();
return function(
segments: UrlSegment[],
segmentGroup: UrlSegmentGroup,
route: Route
) {
let matchSegments = url.split('/');
if (
matchSegments.length > segments.length ||
(matchSegments.length !== segments.length && route.pathMatch === 'full')
) {
return null;
}
let consumed: UrlSegment[] = [];
let posParams: {[name: string]: UrlSegment} = {};
for (let index = 0; index < segments.length; ++index) {
let segment = segments[index].toString().toLowerCase();
let matchSegment = matchSegments[index];
if (matchSegment.startsWith(':')) {
posParams[matchSegment.slice(1)] = segments[index];
consumed.push(segments[index]);
}
else if (segment === matchSegment) {
consumed.push(segments[index]);
}
else {
return null;
}
}
return { consumed, posParams };
}
}
С
@NgModule({
imports: [
...
RouterModule.forRoot([
{ matcher: CaseInsensitiveMatcher('user/:id'), component: ProfileComponent },
])
],
declarations: [
...
],
bootstrap: [
AppComponent
]
})
Изменить: Я только узнал, что для работы с компиляцией AoT часть @NgModule будет выглядеть примерно так:
export function profileMatch() {
return CaseInsensitiveMatcher('user/:id').apply(this, arguments);
}
@NgModule({
imports: [
...
RouterModule.forRoot([
{ matcher: profileMatch, component: ProfileComponent },
])
],
declarations: [
...
],
bootstrap: [
AppComponent
]
})
Ответ 5
Мое обходное решение для этой проблемы:
/* IMPORTS */
let routeEntries = [
{ path: '/home', component: HomePage }
/* DEFAULT ROUTE */
{ path: '/', component: HomePage },
/* NOT FOUND ROUTE */
{ path: '*', component: HomePage }
];
@Component(/* SETUP */)
@Routes(routeEntries)
export App implements OnInit {
/* STUFF */
ngOnInit() {
// subscribe to router changes
this.router.changes.forEach(() => {
let routerLink = location.pathname;
let routerLinkLower = routerLink.toLowerCase();
// if the route does not exist, check for the lowercase version
if (!routeEntries.find((route) => { return route.path === routerLink; })) {
this.router.navigate([routerLinkLower]);
}
// if the route is correct, set the active page
else {
// do something here if required
}
});
}
}
Это работает с маршрутизатором RC1 и хорошо сочетается с вариантами маршрута, например:
'{domain}:{port}/HoMe'
'{domain}:{port}/homE'
'{domain}:{port}/Home'
...
Ответ 6
Небольшое исправление для Timothy answer, которое не меняет случай совпадающих имен параметров и значений:
import {Route, UrlSegment, UrlSegmentGroup} from '@angular/router';
export function caseInsensitiveMatcher(url: string) {
return function(
segments: UrlSegment[],
segmentGroup: UrlSegmentGroup,
route: Route
) {
const matchSegments = url.split('/');
if (
matchSegments.length > segments.length ||
(matchSegments.length !== segments.length && route.pathMatch === 'full')
) {
return null;
}
const consumed: UrlSegment[] = [];
const posParams: {[name: string]: UrlSegment} = {};
for (let index = 0; index < matchSegments.length; ++index) {
const segment = segments[index].toString().toLowerCase();
const matchSegment = matchSegments[index];
if (matchSegment.startsWith(':')) {
posParams[matchSegment.slice(1)] = segments[index];
consumed.push(segments[index]);
} else if (segment.toLowerCase() === matchSegment.toLowerCase()) {
consumed.push(segments[index]);
} else {
return null;
}
}
return { consumed, posParams };
};
}
Изменить: помимо проблемы, описанной выше, есть еще одна тонкая ошибка, которая теперь устранена. Цикл for должен перебирать matchSegments
вместо segments
.
Ответ 7
Вот как я исправил эту проблему
{ path: '/home', redirectTo: ['/Home'] },
{ path: '/Home', component: HomeComponent, name: 'Home' },