More often than not, in a project, certain routes are a requirement, not a developer choice. That said, I agree to those routes too, in the detriment of query params (so called GET variables in php or other server-side languages).
There is a similar question here, however it is a scenario more simple than this one and it doesn't mention anything about solving the "optional" route params order. Nor does it treat a case when we need to have more than one or two "optional" route params (like when you filter the content for various things). It's only about one single "optional" route param. I keep using quotes because, as far as I know, by default there is no such thing as an "optional route parameter", as long as the only way to achieve this is to fake it (as in declaring all possible routes, with and without that param).
For example, as per project requirements, routes need to look like this:
/videos
/videos/categories/cat1_cat2
/videos/tags/tag1_tag2
/videos/categories/cat1_cat2/tags/tag1_tag2
OR
/videos/tags/tag1_tag2/categories/cat1_cat2
NOT like this:
/videos?categories=cat1_cat2&tags=tag1_tag2
Ok, the OR
in the routes example above is my own, not a requirement. Because, even if in this scenario it is not the case (we wouldn't want to allow google or other search engine any chance to see the same content across different routes), still - in other cases - order doesn't matter. And, in those cases, it would be easier for the developer to simply not care about the order in which he/she stacks the filters when generating the route links. By "filter" I'm referring to a segment group such as /categories/:categories
.
Putting the OR
aside, at least the rest is a very common case, in fact all projects I've been involved in had filtering/sorting routes like this, not with query params.
So, having this limitation with angular's router, how would one go about the needed routes?
Sure, off the top of my head, I would think about this kind of setup:
[
{ path: '/videos/categories/:categories/tags/:tags', component: VideosComponent },
{ path: '/videos/categories/:categories', component: VideosComponent },
{ path: '/videos/tags/:tags', component: VideosComponent },
{ path: '/videos', component: VideosComponent }
]
Or maybe using child routes, defining them in a separate file so we won't clutter the main app routes with so much configuration in one place.
SO the above configuration of routes has obvious limitations:
- In the example above we only have up to 2 filters applied
(
categories
andtags
). This would be way too cumbersome if we had 4 or 5 filters. In case of 5 filters for example, we would need to define routes to combine any 1 filter, any 2 filters, any 3 filters, any 4 filters and all 5 filters. Also add pagination to that... and it would be routing configuration hell. I mean, for each of the above routes, add the fact that we may or may not also have/page/:page
(we don't want/page/1
in the url, we only want to have/page
in the url starting with page 2). This simply doubles all the above routes. Maintaining this route configuration has just become a separate project on it's own. - As per the above route configuration, we can only stack segments in the url in a certain order: categories
first, tags second. Sure, we might fix this by setting all the
possible combinations in the configuration of the routes (having both
/categories/:categories/tags/:tags
and/tags/:tags/categories/:categories
), which would be a pain to configure when we have more than 2 filters. It's just way too complicated to maintain. It would be more useful if the router would simply recognize/categories/cat1_cat2
no matter the placement of this segment group among the other segments/segment groups in the url. Sure, this would mean that the configuration would look different from what it is now, because we can also have "single" segments in the url, not only in pairs. But this is something they should have thought about way back, before they've even started to develop the router.
I can't believe that, when building the angular router, they didn't think about this (very common) scenario and offer some kind of helper in order to achieve this kind of customization. Is there something I'm missing? Does the router in fact offer a way to customize something like this, but no one got into that in any tutorial I've happen to see?