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

Feature to bind Router information to component inputs #49633

Closed
wants to merge 5 commits into from

Conversation

atscott
Copy link
Contributor

@atscott atscott commented Mar 29, 2023

Adds ability for RouterOutlet to bind Router information to the routed
component's inputs. This commit also exposes some helpers for
implementers of custom outlets to do their own input binding if desired.

Resolves #18967

Edit to add some more color to the "required inputs" / no references / no compiler warning for the inputs:

  • Some router data lives entirely in userspace and isn't known until runtime. This includes path parameters and query parameters. Only static data or resolve items can be known at compilation time.
  • We considered requiring that bindings be defined in the data or resolve of the Route definitions. However, this would require developers to set the runGuardsAndResolvers option at least to 'pathParamsOrQueryParamsChange'. This was undesirable from a usability and discoverability standpoint.
  • Required inputs are checked by the template type checking. Because these components are created dynamically by the RouterOutlet, required inputs cannot be checked by the compiler. This is also true of any other component created dynamically.
  • We also considered yet another property on Route to define what bindings to set on the component. Similar to the point above, this was much more verbose than desired.
  • There might be some compiler magic we could add to do some level of type checking. However, I feel the Router package should be developed in a way that isn't "special". That is, it's a library that doesn't use any private APIs or integrations that aren't available to any library author. This ensures that the capabilities in the Router can always be replicated in an alternate Routing library driven by the community; I think this is an important property to at least have as a goal for the health of community projects.

@atscott atscott added area: router target: minor This PR is targeted for the next minor release labels Mar 29, 2023
@ngbot ngbot bot modified the milestone: Backlog Mar 29, 2023
@angular-robot angular-robot bot added detected: feature PR contains a feature commit area: docs labels Mar 29, 2023
@GabrielBB
Copy link

GabrielBB commented Mar 29, 2023

If you do "find usages" in your IDE you will see nothing and think it can be removed, right ? This would reduce the confidence while doing code cleanups. I wouldn't go this hidden magical path. Spring Boot uses @QueryParam and @PathParam annotations for REST Controllers, maybe you can so @QueryInput and @PathInput ?

@atscott
Copy link
Contributor Author

atscott commented Mar 29, 2023

If you do "find usages" in your IDE you will see nothing and think it can be removed, right ? This would reduce the confidence while doing code cleanups. I wouldn't go this hidden magical path. Why not a @RoutedInput annotation ?

This would still result in the same behavior with typescript not finding references. You can just as easily add a comment or import {Input as RoutedInput} from '@angular/core'.

@GabrielBB
Copy link

GabrielBB commented Mar 29, 2023

If you do "find usages" in your IDE you will see nothing and think it can be removed, right ? This would reduce the confidence while doing code cleanups. I wouldn't go this hidden magical path. Why not a @RoutedInput annotation ?

This would still result in the same behavior with typescript not finding references. You can just as easily add a comment or import {Input as RoutedInput} from '@angular/core'.

People will miss doing both. Angular, as a framework, should advocate clarity. Because I think clarity brings confidence

@eneajaho
Copy link
Contributor

If you do "find usages" in your IDE you will see nothing and think it can be removed, right ? This would reduce the confidence while doing code cleanups. I wouldn't go this hidden magical path. Why not a @RoutedInput annotation ?

This would still result in the same behavior with typescript not finding references. You can just as easily add a comment or import {Input as RoutedInput} from '@angular/core'.

This makes sense! Thanks.

Copy link
Member

@alxhub alxhub left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed-for: public-api

packages/router/src/directives/router_outlet.ts Outdated Show resolved Hide resolved
packages/router/src/directives/router_outlet.ts Outdated Show resolved Hide resolved
@atscott atscott force-pushed the routerInputBindings branch 2 times, most recently from 20ddb72 to 31768e4 Compare March 29, 2023 23:03
Copy link
Contributor

@jessicajaniuk jessicajaniuk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

reviewed-for: fw-core, public-api

@jessicajaniuk jessicajaniuk removed their request for review March 30, 2023 15:28
…puts

Adds ability for `RouterOutlet` to bind `Router` information to the routed
component's inputs. This commit also exposes some helpers for
implementers of custom outlets to do their own input binding if desired.

Resolves angular#18967
…of ActivatedRoute

The easiest way to access route data is now to use direct bindings to
component inputs rather than going through `ActivatedRoute`.

The tour of heroes guide still uses `ActivatedRoute` for now. I was
hesitant to remove all of the content in one swoop and the tour of
heroes is quite a bit more involved.
@github-actions
Copy link

Deployed aio for 9a018a4 to: https://ng-dev-previews-fw--pr-angular-angular-49633-dtzgtrva.web.app

Note: As new commits are pushed to this pull request, this link is updated after the preview is rebuilt.

@atscott atscott added the action: merge The PR is ready for merge by the caretaker label Mar 30, 2023
@alxhub alxhub added the merge: caretaker note Alert the caretaker performing the merge to check the PR for an out of normal action needed or note label Mar 30, 2023
@alxhub
Copy link
Member

alxhub commented Mar 30, 2023

(same existing failures on TAP as other PRs)

@angular-robot
Copy link
Contributor

angular-robot bot commented Mar 30, 2023

This PR was merged into the repository by commit 81c9dd7.

@angular-robot angular-robot bot closed this in f982a3f Mar 30, 2023
angular-robot bot pushed a commit that referenced this pull request Mar 30, 2023
…of ActivatedRoute (#49633)

The easiest way to access route data is now to use direct bindings to
component inputs rather than going through `ActivatedRoute`.

The tour of heroes guide still uses `ActivatedRoute` for now. I was
hesitant to remove all of the content in one swoop and the tour of
heroes is quite a bit more involved.

PR Close #49633
@MunMunMiao
Copy link

MunMunMiao commented Apr 5, 2023

If you do "find usages" in your IDE you will see nothing and think it can be removed, right ? This would reduce the confidence while doing code cleanups. I wouldn't go this hidden magical path. Why not a @RoutedInput annotation ?

This would still result in the same behavior with typescript not finding references. You can just as easily add a comment or import {Input as RoutedInput} from '@angular/core'.

Previously, 'Input' represented the value passed from the parent component. If the data comes from a Route, decorators such as "RouteParamInput", "RouteQueryInput", and "RouteStaticInput" should be provided to facilitate and strictly distinguish and control the source of the data.

When a sub component needs to pass data from the parent component and also requires query input, it can confuse the developer because they do not know whether the data comes from the parent component or the route.

I know I can set an alias, but it will increase user confusion and increase usage costs.

I think adding new decorators is a better choice.

If the user manually enters a query param on the route, it will cause the value of the Input to be overwritten. At this point, this value is not secure.

like:

I want

@Input() id: Observable<number>

But route is: /user?id=123

@Input() id: // this value is ???

If use RouteQueryInput or RouteParamInput I Know this value is string or undefined

@RouteQueryInput() id?: string
@RouteParamInput() type?: string
@RouteStaticInput() someRouteStaticValue?: unkonw

@atscott

@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators May 16, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker aio: preview area: router detected: feature PR contains a feature commit merge: caretaker note Alert the caretaker performing the merge to check the PR for an out of normal action needed or note target: minor This PR is targeted for the next minor release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow Route Params to be Passed into Component @Inputs
7 participants