X Tutup
The Wayback Machine - https://web.archive.org/web/20230413191042/https://github.com/angular/angular/issues/49309
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include URL parameters in canMatch interface #49309

Open
joelghill opened this issue Mar 3, 2023 · 7 comments
Open

Include URL parameters in canMatch interface #49309

joelghill opened this issue Mar 3, 2023 · 7 comments
Labels
area: router feature: votes required Feature request which is currently still in the voting phase feature Issue that requests a new feature
Milestone

Comments

@joelghill
Copy link

Which @angular/* package(s) are relevant/related to the feature request?

router

Description

The canMatch router guard accepts route: Route and segments: UrlSegment[] as arguments. Neither of these objects contain the parameters that may or may not be in the URL.

Example

A URL path will be set to users/:userId and when the browser navigates to the URL users/user_123 we should have access to a mapping of parameters similar to:

{
    "userId": "user_123",
}

I can't find this information anywhere at the time the canMatch guard is activated. Parameters objects in the URL segments are empty, and the Route object does not have a params object, and using the activate route service also does not provide a solution. Am I doing something wrong?

Proposed solution

Provide an object, either as a canMatch parameter or in the UrlSegment or the Route (I don't really care where they are, whatever makes sense to the Angular routing design) that includes the URL parameters.

Alternatives considered

We can currently take the path in the route, and the URL segments, compare them, and derive the parameters from there.

I feels like shouldn't have to do this though? The canActivate method has access to this data via the activated route snapshot (params object) and I don't understand why we can't have something similar in canMatch?

@atscott atscott added feature Issue that requests a new feature area: router labels Mar 3, 2023
@ngbot ngbot bot added this to the Backlog milestone Mar 3, 2023
@atscott
Copy link
Contributor

atscott commented Mar 3, 2023

The canActivate method has access to this data via the activated route snapshot (params object) and I don't understand why we can't have something similar in canMatch?

This is because canActivate happens after matching. We don't have the parameters information until after matching is finished because the route configuration affects what the parameters are.

It is possible that we could investigate accumulating a set of currently matched parameters up to the point of hitting the Route config and running canMatch.

Note that the lack of having this information is effectively what's blocking this feature request because the experience would be sub-optimal: #13373

@joelghill
Copy link
Author

We don't have the parameters information until after matching is finished because the route configuration affects what the parameters are.

Thanks for responding! I think this is the part I'm confused about. What in the route config can affect parameters at the point in time of executing canMatch? I'd like to understand this better.

For my use case I really need something dead simple to cover most cases:

  1. Route path is something/:something_id -> we currently have this
  2. When we navigate to a URL that matches the above path, Url Segments are ['something', '123456'] -> we currently have these
  3. Parameters are {'something': '123456'} -> this is what I need to perform the canMatch

Unless I'm missing something I could probably write a custom guard that does the parsing I need, I'm just surprised it's not there already and I'm unaware of what in the overall architecture would prevent this. Again, I don't have a deep understanding of what angular is doing under the hood though.

@joelghill
Copy link
Author

I should also add that perhaps canActivate is a better solution in my use case, but it does not come with the benefit of automatically trying a different pattern on failure. Being able to setup a wildcard route with a generic "resource not found" component when none of the routes match is a great feature but I find we really can't replace canActivate with canMatch with it's current interface.

@atscott
Copy link
Contributor

atscott commented Mar 3, 2023

Route path is something/:something_id -> we currently have this

We absolutely have an easy way to access the params of the current route being matched. However these are not final because a redirect may cause parameters and parameter names to change. You can get this information manually by just rerunning the matcher on those segments in your guard:

canMatch: [
          (route: Route, segments: UrlSegment[]) => {
            const matcher= route.matcher || defaultUrlMatcher;
            const matchResult = matcher(
              segments,
              new UrlSegmentGroup(segments, {}),
              route
            );
            console.log(matchResult);
            return true;
          },
        ],

https://stackblitz.com/edit/angular-6m5gvr?file=src%2Fmain.ts

These are just the current route though and again as I mentioned above, we don't currently pass down the parameter matches from the parent configs (you also would definitely not have access to any child parameters no mater what). Also, because we haven't matched all the parent's children, we can't construct the parent tree object (UrlSegmentGroup or ActivatedRoute) until this is done.

Parameters are {'something': '123456'} -> this is what I need to perform the canMatch
...
guard accepts route: Route and segments: UrlSegment[] as arguments. Neither of these objects contain the parameters that may or may not be in the URL.

I think part of the confusion is that the parameters on UrlSegment are not the path parameter names in the route config. These would be the matrix parameters like in a URL /a;something_id=1234.

Long story short, I do think this is a problem that we should fix, especially if we want to land #13373 (and we do). I would guess that nobody really thought about this before.

@angular-robot angular-robot bot added the feature: votes required Feature request which is currently still in the voting phase label Mar 4, 2023
@angular-robot
Copy link
Contributor

angular-robot bot commented Mar 4, 2023

This feature request is now candidate for our backlog! In the next phase, the community has 60 days to upvote. If the request receives more than 20 upvotes, we'll move it to our consideration list.

You can find more details about the feature request process in our documentation.

@joelghill
Copy link
Author

Thank you @atscott, your response and sample code was super helpful!

I was eventually able to get done what I needed to with the canMatch guard but I think there is more information that could be surfaced to the developer at the time the guard is executed.

@angular-robot
Copy link
Contributor

angular-robot bot commented Apr 13, 2023

Just a heads up that we kicked off a community voting process for your feature request. There are 20 days until the voting process ends.

Find more details about Angular's feature request process in our documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: router feature: votes required Feature request which is currently still in the voting phase feature Issue that requests a new feature
Projects
None yet
Development

No branches or pull requests

2 participants
X Tutup