Reputation: 353
I have an issue with Angular routing I have two modules Basic and Dashboard
In the basic module, I can pass city param for not default city (for default city it should work without param, for example, if New York is default city the path will be http://my.domain/new-york and APP should use HomeComponent) but for not default application should use path http://my.domain/los-angeles and use the same component. List of cities I've got from the back-end. Next level of my structure is categories. I've got categories from the back-end too, but if I try to go to the http://my.domain/category I've got HomeComponent instead of SearchComponent. What the correct way to handle that?
I need:
http://my.domain/category -> SearchComponent
http://my.domain/city/category -> SearchComponent
http://my.domain/city -> HomeComponent
http://my.domain/ -> HomeComponent
app route config:
const routes: Routes = [
{
path: 'dashboard',
canActivate: [AuthService],
loadChildren: () => import('./modules/dashboard/dashboard.module').then(mod => mod.DashboardModule)
},
{
path: '',
loadChildren: () => import('./modules/basic/basic.module').then(mod => mod.BasicModule),
runGuardsAndResolvers: 'always'
},
{
path: '**',
redirectTo: '/'
}
];
Basic module routing
const routes: Routes = [
{
path: '',
component: BasicComponent,
children: [
{
path: '',
component: HomeComponent,
data: {
headerDark: true
}
},
{
path: 'search',
component: SearchComponent,
pathMatch: 'full'
},
{
path: ':city',
component: HomeComponent,
data: {
headerDark: true
},
},
{
path: ':category',
component: SearchComponent
},
{
path: ':city/:category',
component: SearchComponent
},
{
path: ':city/search',
component: SearchComponent,
data: {
headerDark: true
}
}
]
}
];
Upvotes: 1
Views: 1413
Reputation: 11924
I think you can solve it by implementing a custom UrlMatcher
.
Here's the type definition for UrlMatcher
:
export type UrlMatchResult = {
consumed: UrlSegment[];
posParams?: {[name: string]: UrlSegment};
};
export type UrlMatcher = (segments: UrlSegment[], group: UrlSegmentGroup, route: Route) =>
UrlMatchResult|null;
Angular uses a defaultUrlMatcher
for each of the route configuration objects. Its role is to determine the positional params(e.g :city
) and the consumed segments(the segments that match the issued URL):
/* ... */
for (let index = 0; index < parts.length; index++) {
const part = parts[index];
const segment = segments[index];
const isParameter = part.startsWith(':');
if (isParameter) {
posParams[part.substring(1)] = segment;
} else if (part !== segment.path) {
// The actual URL part does not match the config, no match
return null;
}
}
return {consumed: segments.slice(0, parts.length), posParams};
With this in mind, we could create a custom UrlMatcher
that looks like this:
const cityMatcher: UrlMatcher = (segments, group, route) => {
// you'll have to find the issued city name from `segments`
// simply use console.log(segments) to find the proper way to do it
// after you've found the name of the city, check if it is in the list of cities
// if NOT in the list
return null
// if it is there
return {
consumed: segments.slice(0, 1),
posParams: { city: nameOfTheFoundCity }
}
}
And can be used like this:
{
{
path: ':city',
component: HomeComponent,
data: {
headerDark: true
},
matcher: cityMatcher
},
}
The same approach can be used for :category
.
Upvotes: 3
Reputation: 573
I don't have the answer for you, but it probably has something to do with the path matching strategy.
Look here to see if adding pathMatch: 'Full' to one of your routes can solve your problem! I don't know which exact route you should add the pathMatch full strategy to but I believe the answer to your problem lies here.
Cheers
Upvotes: 0