Reputation: 2255
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?
Upvotes: 1
Views: 1732
Reputation: 2255
I am adding another answer, since I also needed to use the @user123/edit
path, but it didn't work with the original solution. So here is how to do it:
app-routing.module.ts
{
matcher: (url) => {
console.log(url);
if (url[0].path.match(/^@[\w.\-]+$/gm)) { <-- removed check for url length
return {
consumed: url.slice(0, 1), <-- return the rest of the URL instead of the whole URL (this routing rule should only consume @user123 and return the rest of the URL, which is /edit)
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
},
{
path: 'edit',
component: EditProfileComponent
},
Upvotes: 0
Reputation: 2255
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]);
}
});
});
}
Upvotes: 1
Reputation: 3171
You can make use of custom route matcher
to achieve the expected result.
{
path: 'profile',
loadChildren: () => import('./modules/profile/profile.module').then(m => m.ProfileModule)
},
custom URL-matching function
as: {
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
}
username
as: username$!: Observable<string | null>;
constructor(private activatedRoute: ActivatedRoute) { }
ngOnInit(): void {
this.username$ = this.activatedRoute.paramMap
.pipe(
map((params: ParamMap) => params.get('username'))
);
}
<p>
Profile: {{username$ | async}}
</p>
/profile/@user123
and you should be able to get user123
as username in ProfileComponentUpvotes: 2