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

Ability to request injection from a specific parent injector #40974

Closed
waterplea opened this issue Feb 24, 2021 · 11 comments
Closed

Ability to request injection from a specific parent injector #40974

waterplea opened this issue Feb 24, 2021 · 11 comments
Assignees
Labels
area: core Issues related to the framework runtime core: di feature: under consideration Feature request for which voting has completed and the request is now under consideration feature: votes required Feature request which is currently still in the voting phase feature Issue that requests a new feature
Milestone

Comments

@waterplea
Copy link
Contributor

waterplea commented Feb 24, 2021

Title edited from: Add options to @Inject decorator to read particular provider

🚀 feature request

Relevant Package

This feature request is for @angular/core

Description

When we use @ViewChild/ren or @ContentChild/ren we can query using DI token and then provide additional read option to tell what other token do we want to actually read from it:

@ViewChild(MyDirective, { read: ElementRef })
readonly element: ElementRef;

It would be super awesome if we could do it with constructor params!

Describe the solution you'd like

Add options to @Inject decorator:

constructor(@Inject(MyContainer, {read: ElementRef}) private readonly myContainerElement: ElementRef) {}

Describe alternatives you've considered

Create tokens and add useExisting providers to directives, but it's not always known beforehand what tokens I might need to inject later on.

Use cases:

  1. Querying ElementRef of a particular parent element
  2. Querying ChangeDetectorRef of a wrapping element so content children can trigger change detection of their OnPush parent
@petebacondarwin petebacondarwin added area: core Issues related to the framework runtime core: di feature Issue that requests a new feature labels Feb 24, 2021
@ngbot ngbot bot modified the milestone: Backlog Feb 24, 2021
@petebacondarwin
Copy link
Member

@waterplea - it would be really helpful in setting a priority for this feature, if you were to give some concrete examples of scenarios where this would be useful.

@waterplea
Copy link
Contributor Author

Well, the example with ElementRef is the most frequent case I need it. The most recent case was resizable columns. I have a directive for a draggable bar to resize parent TH element but I need to get its initial width when I start dragging:
https://stackblitz.com/edit/angular-resizable-columns?file=src%2Fapp%2Fresizable%2Fresizable.directive.ts
See lines 23/24. Would love to just inject that TH native element because it's a separate component, but instead I need to either provided it with useExisting and a token in the parent TH component or rely on native API like I did in this example.

@petebacondarwin
Copy link
Member

This is how I would have constructed this example. Is that one of the options you considered?
https://stackblitz.com/edit/angular-resizable-columns-vcjngi?file=src%2Fapp%2Fresizable%2Fresizable.directive.ts

@waterplea
Copy link
Contributor Author

Now I solve these things with tokens, it's cleaner than injecting stuff in parent container that it doesn't need:
https://github.com/TinkoffCreditSystems/taiga-ui/blob/main/projects/addon-table/components/resizable-column/resizable-column.component.ts

But I'm not looking for workarounds, I'm just saying if we can query stuff inwards with children, it would help to be able to do it upward.

@petebacondarwin
Copy link
Member

Right, thanks for providing the component provider approach. This is all helpful in working out the priority for this.

For what it's worth I would not expect a second decorator, but instead a parameter on @Inject() similar to how @ViewChild() works:

constructor(@Inject(MyContainer, {read: ElementRef}) private readonly myContainerElement: ElementRef) {}

@waterplea
Copy link
Contributor Author

Another viable usecase!
When we have the following structure:

<parent>
  <child></child>
</parent>

Both parent and child are members of the same view, so there's no way for child to trigger change detection inside parent. Their ChangeDetectorRefs are parallel. But if we could do @Inject(Parent, { read: ChangeDetectorRef }) we could inject the one from the parent and trigger change detection in parent view when necessary.

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

angular-robot bot commented Jun 4, 2021

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.

@waterplea waterplea changed the title Add @Read dependency injection decorator Add options to @Inject decorator to read particular provider Jun 7, 2021
@waterplea
Copy link
Contributor Author

Edited title and body of the request to the options object for @Inject decorator as @petebacondarwin suggested. Please vote if this issue is relevant to you :)

@angular-robot angular-robot bot added the feature: under consideration Feature request for which voting has completed and the request is now under consideration label Jun 8, 2021
@alxhub alxhub added this to Inbox in Feature Requests via automation Jul 29, 2021
@alxhub alxhub moved this from Inbox to Needs Discussion in Feature Requests Jul 29, 2021
@alxhub alxhub changed the title Add options to @Inject decorator to read particular provider Ability to request injection from an arbitrary parent injector Aug 19, 2021
@alxhub alxhub changed the title Ability to request injection from an arbitrary parent injector Ability to request injection from an specific parent injector Aug 19, 2021
@alxhub alxhub changed the title Ability to request injection from an specific parent injector Ability to request injection from a specific parent injector Aug 19, 2021
@alxhub alxhub moved this from Needs Discussion to Close with Followup in Feature Requests Aug 19, 2021
@alxhub alxhub self-assigned this Aug 19, 2021
@alxhub alxhub removed this from Close with Followup in Feature Requests Aug 19, 2021
@alxhub
Copy link
Member

alxhub commented Jun 23, 2022

While this is an interesting idea, I don't think it's a feature we would want to add to the DI system. A strong argument against is that it breaks the natural encapsulation provided by DI, where a parent can choose to override providers being passed to the children. Being able to reach into the parent injector and inject tokens directly breaks that encapsulation.

@alxhub alxhub closed this as not planned Won't fix, can't repro, duplicate, stale Jun 23, 2022
@waterplea
Copy link
Contributor Author

In case someone's interested, I was playing with new inject function from Angular 14 and out of challenge I've made a solution to reach for particular parent's provider through it 😀 The key is using inject inside forwardRef to walk injectors upwards until we reach target injector, then query our provider from it and store it in a token we create inside a closure. Absolute nuts, but all through public APIs 😁
https://gist.github.com/waterplea/4d31fb15782769cad0b292976b95805b

@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 Jul 26, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: core Issues related to the framework runtime core: di feature: under consideration Feature request for which voting has completed and the request is now under consideration 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

3 participants