Reputation: 523
For legacy reasons I am required to handle a route where there is potential for there to be two slashes back to back because there is an optional id in the path (e.g. /base//child/2). I can not change the url in anyway (like omitting the double slashes in favor of a secondary route). Is there anyway I can get the angular router to recognize this url and either redirect it or handle it?
This minimal stackblitz example shows the problem.
Upvotes: 1
Views: 3098
Reputation: 342
It seems Angular can not parse url with double slash correctly, so the routing path mapping will not work. You can implement your own UrlSerializer
instead of using the default DefaultUrlSerializer
. Try to convert path "/base//child/1" to "/base/child/1".
import {UrlSerializer, UrlTree, DefaultUrlSerializer} from '@angular/router';
export class CustomUrlSerializer implements UrlSerializer {
parse(url: any): UrlTree {
let dus = new DefaultUrlSerializer();
console.log(url);
if(/\/\//.test(url)) {
url = url.replace(/\/\//, '/');
}
return dus.parse(url);
}
serialize(tree: UrlTree): any {
let dus = new DefaultUrlSerializer(),
path = dus.serialize(tree);
return path;
}
}
Register it in app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { RouterModule, UrlSerializer } from '@angular/router';
import { CatchAllComponent } from './catch-all/catch-all.component';
import { InformedComponent } from './informed/informed.component';
import { CustomUrlSerializer } from './custom-url-serializer';
@NgModule({
imports: [
BrowserModule,
FormsModule,
RouterModule.forRoot([{
path: 'base/child/:id',
component: InformedComponent,
}, {
path: 'base/:parentId/child/:id',
component: InformedComponent
}, {
path: '**',
component: CatchAllComponent
}])
],
declarations: [ AppComponent, CatchAllComponent, InformedComponent ],
providers: [
{ provide: UrlSerializer, useClass: CustomUrlSerializer }
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Now the url with double slash "//" will be converted to "/". It will match the routing path "base/child/:id", so you can get the params and handle it.
Upvotes: 3
Reputation: 2420
I'd try with UrlMatcher something along these lines
matcher.ts
import { UrlSegment } from '@angular/router';
export function matcher(url: UrlSegment[]) {
console.log(JSON.stringify(url));
return url.length === 1 && url[0].path === 'base' ? ({consumed: url}) : null;
}
routes
import { matcher } from './matcher';
RouterModule.forRoot([{
matcher: matcher,
component: InformedComponent
}, {
path: 'base/:parentId/child/:id',
component: InformedComponent
}, {
path: '**',
component: CatchAllComponent
}])
]
Tried this with your stacknblitz and it works. Not sure but other options could be listening to router's navigation started event or a route guard.
Upvotes: 2