I want to implement the user profile page. It would be simple to just use the
/profile/user123 path using:
app-routing.module
{
path: 'profile',
loadChildren: () => import('./modules/profile/profile.module').then(m => m.ProfileModule)
},
profile-routing.module
{
path: ':username',
component: ProfileComponent
},
however, I want to do some fancy URL like /@user123.
Unfortunately, I did not find any clues on how to do it. I tried the following:
app-routing.module
{
path: '@:username',
loadChildren: () => import('./modules/profile/profile.module').then(m => m.ProfileModule)
},
profile-routing.module
{
path: '',
component: ProfileComponent
},
but it didn't work.
There is only one thing that comes to my mind, which is using a Guard checking for the '@' prefix, otherwise redirect to the /not-found page.
Any ideas on how to do the routing using the "Angular" way?
CodePudding user response:
You can make use of custom route matcher to achieve the expected result.
- app-routing.module.ts
{
path: 'profile',
loadChildren: () => import('./modules/profile/profile.module').then(m => m.ProfileModule)
},
- In profile-routing.module.ts you can specify a route by providing
custom URL-matching functionas:
{
matcher: (url) => {
// You can have regex as per your requirement
if (url.length === 1 && url[0].path.match(/^@[\w] $/gm)) {
return {
consumed: url,
posParams: {
username: new UrlSegment(url[0].path.substr(1), {}) // <--- creating UrlSegment by getting rid of @ from url path
}
};
}
return null;
},
component: ProfileComponent
}
- In profile.component.ts file you can read the
usernameas:
username$!: Observable<string | null>;
constructor(private activatedRoute: ActivatedRoute) { }
ngOnInit(): void {
this.username$ = this.activatedRoute.paramMap
.pipe(
map((params: ParamMap) => params.get('username'))
);
}
- In profile.component.html you can print the username as:
<p>
Profile: {{username$ | async}}
</p>
- Now simply navigate to url
/profile/@user123and you should be able to getuser123as username in ProfileComponent
CodePudding user response:
The solution provided by Siddhant is excellent, but I wanted /@user123 instead of /profile/@user123, so I tweaked it a little.
app-routing.module.ts
{
matcher: (url) => {
if (url.length === 1 && url[0].path.match(/^@[\w.\-] $/gm)) { // <--- added a hyphen and a dot, since \w only does [a-zA-Z0-9_]
return {
consumed: url,
posParams: {
username: new UrlSegment(url[0].path.substr(1), {}) // <--- creating UrlSegment by getting rid of @ from url path
}
};
}
return null;
},
loadChildren: () => import('./modules/profile/profile.module').then(m => m.ProfileModule)
},
profile.routing.module.ts
{
path: '',
component: ProfileComponent
},
profile.component.ts
ngOnInit(): void {
this.activatedRoute.paramMap.subscribe(paramMap => {
this.userService.getUser(paramMap.get('username')).subscribe(res => {
if (res) {
this.user = res;
} else {
this.router.navigate([Utils.ARTICLE_NOT_FOUND_URL]);
}
});
});
}
