angular: Nested multiple levels of ContentChild query returns undefined

I’m submitting a…


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

When ng-content is used on multiple levels, only the first component is able to find the ContentChild.

Expected behavior

I think every parent component at each level should be able to find the ContentChild. Please see the plunker example.

Minimal reproduction of the problem with instructions

https://plnkr.co/edit/iMDKo9cdKeyB0Y4is11y?p=preview

What is the motivation / use case for changing the behavior?

I have a div[myFormElement] component that projects an input. Based on what kind of input it is, I would like to add extra functionality, but I would like to separate that logic from the div[myFormElement] component and only include it in my-custom-wrapper-component.

<div myFormElement>
  <input myInput />  
</div>
<div myFormElement>
  <input mySpecialInput />
</div>

Then in the my-form-element component,

@ContentChild(myInput) inputElement: myInput;
@ContentChild(mySpecialInput) specialElement: mySpecialInput;

<div *ngIf="myInput">
  <ng-content select="[myInput]"></ng-content>
</div>
<div *ngIf="mySpecialInput">
  <my-custom-wrapper-component> <!-- This component adds extra functionality that my-form-element shouldn't be concerned with -->
    <ng-content select="[mySpecialInput]"></ng-content>
  </my-custom-wrapper-component>
</div>

In my-custom-wrapper-component, @ContentChild() is returning undefined.

@ContentChild(mySpecialInput) specialElement: mySpecialInput; // This is returning undefined

<ng-content></ng-content>

Environment


Angular version: Latest

Browser:
- [x] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 2
  • Comments: 19 (7 by maintainers)

Most upvoted comments

@jpzwarte this is a good use-case, thnx! I would say that it should be solved through #8563 (that is - better, more dynamic content projection system). I hope that we will get to it pos-ivy. I’m going to add your use-case to #8563, thnx!

@pkozlowski-opensource I’m writing a <foo-user-menu> component that uses MatMenu. The FooUserMenu component contains 1 menu item by default (“Log out”), but an application can add additional menu items via content projection.

foo-user-menu.component.html:

<mat-menu>
  <ng-content></ng-content>
  <button mat-menu-item>Log out</button>
</mat-menu>

app.component.html:

<foo-user-menu>
  <button mat-menu-item>Settings</button>
</foo-user-menu>

So FooUserMenu first projects the content inside it’s own template, then MatMenu projects it inside itself. The content projection works fine, but @ContentChildren inside MatMenu doesn’t.