[go: nahoru, domu]

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

Allow providers added by our view child to be accessed in our content child #56822

Closed
csisy-bt4w opened this issue Jul 3, 2024 · 1 comment
Closed
Labels
area: core Issues related to the framework runtime core: content projection core: queries
Milestone

Comments

@csisy-bt4w
Copy link
csisy-bt4w commented Jul 3, 2024

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

core

Description

Consider the following scenario:

A component wants to render user-specified content. This can easily be achieved with contentChildren queries for a custom directive:

// ts
protected readonly markers = contentChildren(MyMarkerDirective);

// html
@for (marker of markers(); track marker) {
  <ng-container *ngTemplateOutlet="marker.templateRef"/>
}

However, we want to wrap this component inside another component but we want to keep the possibility to provide user-specified content.

Since nested content projection still doesn't work as one could expect (e.g. #47732), we thought that instead of a contentChildren query, we would invert the whole dependency tree: register a container in the component that previously used the children query and the directive would directly register itself into this container.

However, this still does not work because the instance provided by the component is not available in a directive created through content projection. See the following stackblitz for a complete example: https://stackblitz.com/edit/stackblitz-starters-yle9g4?file=src%2Fmain.ts

In summary, we have the following component tree:

app
 |-- wrapper component (view child of app)
       |-- marker handler (view child of wrapper component)
             |-- template with marker directive (view child of app, content child of wrapper component, SHOULD BE view/content child of the marker handler)

We want to access the injectable instance provided by the marker handler in the marker directive.

Proposed solution

The injector tree should consider the view/content relation even for projected content that comes from outside. That way we could work around the nested projection issue by inverting the dependency graph. And it would work n-deep as well.

// caller side
<my-wrapper>
  <p myDirective>Hello</p>
</my-wrapper>

// wrapper
<my-cool-component>
  <my-another-component>
    <my-component-interested-in-directive> <!-- container provided here -->
      <ng-content/> <!-- myDirective projected here should be able to see the container -->
    </my-component-interested-in-directive>
  </my-another-component>
</my-cool-component>

Alternatives considered

In the linked stackblitz, we created an ugly workaround where the component that previously used a content query re-provides the container. In addition to being an ugly workaround, it might cause unexpected results (e.g. finding a container that should not be found, etc.).

@thePunderWoman thePunderWoman added the area: core Issues related to the framework runtime label Jul 3, 2024
@ngbot ngbot bot added this to the needsTriage milestone Jul 3, 2024
@pkozlowski-opensource
Copy link
Member

I don't think we should change the way view / content providers work to work-around another issue. Rather, we should find a solution for the scenario described in #47732.

Please note that #47732 is tricky since queries don't descent into components on purpose (otherwise it would break encapsulation and expose all template details to the outside world.

Closing as a duplicate of #47732

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: core Issues related to the framework runtime core: content projection core: queries
Projects
None yet
Development

No branches or pull requests

3 participants