Matching dynamic routes against URLs

— 5 minute read

A few weeks ago I was working on a prototype where I needed to load Custom Elements based on routes within an Angular application.

Using the Angular UrlMatcher, it is possible to match certain routes to URLs. And this was the right tool for the job.

As the docs of Angular state UrlMatcher is:

A function for matching a route against URLs. Implement a custom URL matcher for Route.matcher when a combination of path and pathMatch is not expressive enough. Cannot be used together with path and pathMatch.

An implementation could look like this.

export function matchVillains(url: UrlSegment[]) {
// Logic here
}

const routes: Routes = [
{ path: 'heroes', component: HeroesComponent },
{ path: 'detail/:id', component: DetailComponent },
{ matcher: matchVillains, component: VillainsComponent }
];

As the prototype evolved I wanted to fetch my routes through an API and adapt the matcher to use this data, but apparently this is something UrlMatcher does not allow.

Matching dynamic routes permalink

Angular Router exposes a function called resetConfig that allows to redefine the route configuration used for routing and generating links.

When the Routing module is instantiated and the constructor is executed I call the API that provides the dynamic routes for the matcher. Once I receive the routes I merge the matcher route definition with the other route definitions stored in the routes constant. I'm using the spread operator to combine the matcher definition and routes constant in a newRoutes array.

@NgModule({
imports: [
RouterModule.forRoot([...routes]),
],
exports: [RouterModule],
})
export class AppRoutingModule {

constructor(private router: Router, private villainService: VillainService) {
this.villainService.loadRoutes().subscribe(villainRoutes=> {
const newRoutes = [
{
matcher: (segments: UrlSegment[]) => {
if (segments.length && villainRoutes.filter((route) => segments[0].path === route.path).length >= 1) {
return { consumed: segments };
}
return null;
},
component: VillainsComponent
},
...routes
];
this.router.resetConfig(newRoutes);
});
}
}

So there you have it. Using a combination of UrlMatcher and resetConfig, it is possible to dynamically match routes fetched from an API.