Accessing @ViewChild and @ViewChildren of a template declared in a different component than the one where it is host
See original GitHub issueWhich @angular/* package(s) are relevant/releated to the feature request?
common, core
Description
We can’t access template’s view children from the component that host the template via ngTemplateOutlet
if the template is not declared inside this same component.
For example:
- A child component takes a
TemplateRef
as a@Input()
and insert this template throughngTemplateOutlet
. - A parent component inject the template.
- The child component can’t access views inside the template.
child.component.html
<ng-container #fromParent [ngTemplateOutlet]="template"></ng-container>
child.component.ts
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css'],
})
export class ChildComponent implements AfterViewInit {
@Input() template: TemplateRef<unknown>;
@ViewChildren(HelloComponent) hello = new QueryList<HelloComponent>();
ngAfterViewInit() {
console.log('Has hello', this.hello.length > 0);
}
}
parent.component.html
<ng-template #tmp> <hello name="{{ name }}"></hello> </ng-template>
<app-child [template]="tmp"> </app-child>
The log in child component returns false
.
I already made a StackOverflow
post at https://stackoverflow.com/q/69709254/3520621.
Their is a StackBlitz
available for reproductivity at https://stackblitz.com/edit/angular-eopzyw?file=src/app/app.component.ts.
Proposed solution
I’m not sure of what could be a proper solution but as Ritesh Waghela mentioned in the StackOverflow
post, the template content has the same host id
as the parent component and not the same as the child component.
Maybe the template content should in this case be attached to the child and not the parent ? But I’m not sure if this won’t break any actual behaviour.
In this example the ngcontent host id
shoulld have been lhp-c2
instead of lhp-c0
.
Alternatives considered
In case the template should be use only once, using the power of Content-Projection should do the trick but in my real-life context the template should be reusable. The child-component
must be able to set a ngTemplateOutletContext
.
Anyway, I’m open to any proposition of an alternative way to access the template’s views from child component by keeping the dynamic and reusable power of ng-template
.
Thanks.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:18
- Comments:10 (4 by maintainers)
Top GitHub Comments
So… there is still hope 😃
When I use templates nested, I want to access the component tree through the injector. But after the current template is nested, the tree structure of the content cannot be obtained at all. I don’t know why the template is designed like this, which is a bit contrary to common sense.