Repository navigation
UrlMatcher as a service #17145
Description
I'm submitting a ... (check one with "x")
[ ] bug report => search github for a similar issue or PR before submitting
[x] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
Current behavior
Only a function can be set as the urlMatcher of a route.
const routes = [{
urlMatcher: (segments: UrlSegment[], segmentGroup: UrlSegmentGroup, route: Route) => {
/* Do stuff */
},
component: MyComponent,
}]
Expected behavior
A DI-resolved service or function can be set as the urlMatcher allowing for further injection. I'd expect this to work in an identical way to how the resolver properties can either be services that implement the Resolve<T> interface OR can be an inline resolve() function.
const routes = [{
urlMatcher: MyUrlMatcherService,
component: InterruptComponent,
},
{
path: ":id",
component: ListComponent, /* Contains a <router-outlet> for routing children */
children: [ /*children with sub-paths for deep linking */ ]
}];
@Injectable()
export class MyUrlMatcherService {
constructor(myStateService:MyStateService){}
matchUrl(segments: UrlSegment[], segmentGroup: UrlSegmentGroup, route: Route):UrlMatchResult {
if (!this.myStateService.isInterrupt) return null;
/* Do matching stuff */
}
}
Minimal reproduction of the problem with instructions
N/A
What is the motivation / use case for changing the behavior?
My use case is that InterruptComponent should resolve if some system state (managed by a service) is currently true. If not, I want to skip this route an let other routes attempt matching. In my case I want to greedily consume the entire sub-path and display a specific component, but only in certain circumstances.
Please tell us about your environment:
N/A
- Angular version: 4.X
- Browser: N/A
- Language: TypeScript 2.2+
- Node (for AoT issues): N/A
Activity
[-]UrlMatcher as a servcice[/-][+]UrlMatcher as a service[/+]Dok11 commentedon Sep 7, 2017
Hi all! Have any news about this brilliant feature?
MatissJanis commentedon Mar 28, 2018
Would be absolutely amazing if we could have this!
skorenb commentedon Jun 18, 2018
Also, it would be nice to have an ability to return
Promise<UrlMatchResult >inmatchUrlfunctionDok11 commentedon Jun 18, 2018
@KorenB why
Promise? It is one-time action?I think what matchUrl can runs several times, so it must be is Observble.
skorenb commentedon Jun 19, 2018
@Dok11 , you're right! it should support Observable. Because sometimes i need to call api before the matcher has resolved
adrigardi90 commentedon Jul 11, 2018
I agree! If the matchUrl function could support asynchronous behaviour, would be really good
EddyP23 commentedon Aug 30, 2018
@KorenB, do you have a workaround for the case when you need to call API before the matcher has resolved?
EddyP23 commentedon Aug 30, 2018
and +1 for the feature, would be very useful
amandabot commentedon Aug 30, 2018
@EddyP23
In our application, we need information about a user from a remote source to determine which route to use. We load the user at login time and cache it in a service, as well as storing a global reference to the Angular injector. The matcher imports the injector, finds the user service, and returns the cached user through
Observable.of(), which is synchronous. It's a bit hacky, but it works.In short, the route which needs an asynchronous matcher would need to be preceded by a route that doesn't, and that initial route would need to get the remote information via a resolver or a service injected into a component.
If your workflow doesn't give you the opportunity to preload the data, you could have a route that presents a loading screen with a distinct URL, do the async request, and redirect to the route with the async matcher.
joselcvarela commentedon Aug 7, 2019
It's been a year since last comment and I would love to have this feature on my application.
Specifically I would want to inject Ngrx Store into matcher so I can conditionally match the route accordingly to my store.
SachinShekhar commentedon Jan 1, 2020
I also need this feature badly. It'd be much easier to inject other services into this than grabbing Injector instance from main.ts. Plus, asynchronous path matching is a necessity. Unfortunately, matcher doesn't take async functions.
Example Use Case: A URL segment can represent a tweet, user, group and I want to lazily load a module only after finding out what this segment is post API call.
11 remaining items
krokofant commentedon Oct 18, 2021
@atscott I forgot to think about the combination of the existing UrlMatcher with a
CanUseguard. It would be much cleaner with a one-two punch approach of first matching the URLs and then deciding if they're usable.I can't figure out any good example. 😅
OysteinAmundsen commentedon Nov 26, 2021
I have an example where I need this:
In my application I use a rather complex tree structured hierarchy of nodes of different types. The currently selected node is available from a service and each time a node is selected its entire path is rendered in the url as query params. The reason for this, is that the selected node structure is used accross several different routes. But the queryparams is not necessarily ordered as this can be invoked externally as well, so I depend on having the service available for determining which node is the currently selected one. For this one route in my app, which is for configuring nodes of specific types, each node type has its specific component.
Right now, I do this is done inside a component wrapper where I run
const node = service.getSelectedNode()and in the template several*ngIf="node.type === 'someType'to invoke the destination component.What I would like to do is:
But the
AssetTreeServiceneeds to be injected somehow.Now that I think about it, can I configure the RouterModule injected to the module from the module constructor (where the injector is available)?
feat(router): Add CanMatch guard to control whether a Route should match
angular-automatic-lock-bot commentedon Jul 14, 2022
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.