Problem: I am configuring routes for my application. I want to have my url like https://localhost:4200/hero=id where id will be what ever user selects from Heroscomponent.This is not working for me.
if I try below url whose path is /hero/:id as per angular docs it works phonemically.
https://localhost:4200/hero/:id
Can some please provide me a solution to this problem.
This is my route config file where
const appRoutes: Routes = [
{ path: 'hero', component: HeroesComponent },
{path: 'hero{=:id}', component: HeroDetailComponent},
{
path: 'home',
redirectTo: '/hero',
data: { title: 'Heroes List' }
},{
path: 'student',
component: AppTable
},{
path: 'video',
component: VideoTagComponent
},{ path: '',
redirectTo: '/hero',
pathMatch: 'full'
}
// { path: '**', component: PageNotFoundComponent }
];
Below is my HeroesComponent file where i am routing to path = "/hero="+id
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import {Hero} from './hero';
const HEROES: Hero[] = [
{ id: 11, name: 'Mr. Nice' },
{ id: 12, name: 'Narco' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' },
{ id: 16, name: 'RubberMan' },
{ id: 17, name: 'Dynama' },
{ id: 18, name: 'Dr IQ' },
{ id: 19, name: 'Magma' },
{ id: 20, name: 'Tornado' }
];
@Component({
selector: 'my-heroes',
templateUrl: './heroes.html',
styleUrls: ['./app.component.css']
})
export class HeroesComponent {
hero = HEROES;
path:string;
selectedHero: Hero;
constructor(private router: Router){}
onSelect(hero: Hero): void {
this.selectedHero = hero;
this.path = "/hero=" +this.selectedHero.id.toString();
this.router.navigate([this.path]);
}
// gotoDetail(): void {
// }
}
This is the error i am getting in the browser console.
core.es5.js:1020 ERROR Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'hero%3D13'
Error: Cannot match any routes. URL Segment: 'hero%3D13'**strong text**
I found a solution to this problem.
Because Angular don't support this.. So, we can create a CustomUrlSerializer
import { UrlSerializer, UrlTree, DefaultUrlSerializer } from '@angular/router';
export class CustomUrlSerializer implements UrlSerializer {
public parse(url: any): UrlTree {
let _serializer = new DefaultUrlSerializer();
return _serializer.parse(url.replace('=', '%3D'));
}
public serialize(tree: UrlTree): any {
let _serializer = new DefaultUrlSerializer();
let path = _serializer.serialize(tree);
// use regex to replace as per the requirement.
return path.replace(/%3D/g, '=');
}
}
import this module where you are bootstrapping your AppComponent
import { CustomUrlSerializer } from 'file path';
@NgModule({
bootstrap: [ AppComponent ],
imports: [
],
providers: [
{ provide: UrlSerializer, useClass: CustomUrlSerializer},
]
})
In Your routing module create a matcher for mapping the route.
export const ROUTES: Routes = [
{ matcher: pathMatcher, component: ComponetName},
];
const KEYWORD = /hero=([^?]*)/;
export function pathMatcher(url: UrlSegment[], group: UrlSegmentGroup, route: Route): any {
if (url.length >= 1) {
const [part1] = url
if (part1.path.startsWith('hero')) {
const [,keyword] = KEYWORD.exec(part1.path) || ['',''];
let consumedUrl: UrlSegment[] = [];
consumedUrl.push(url[0]);
return {
consumed: consumedUrl,
posParams: { //The parameters if any you want to pass to ur component
heroId: new UrlSegment(keyword,{})
}
}
}
}
return null
}
Now, In your component you can fetch the heroId by using
this.route.params.subscribe((params)=>{
this.data = params['heroId'];
})
where route is instance of ActivatedRoute