[英]ViewChild from ngTemplateOutlet coming from parent component
I have a child component which accept a TemplateRef
as an @Input
and displays it through ngTemplateOutlet
.我有一个子组件,它接受
TemplateRef
作为@Input
并通过ngTemplateOutlet
显示它。 How can I use @ViewChild
/ @ViewChildren
to retrieve components inside the template ?如何使用
@ViewChild
/ @ViewChildren
检索模板内的组件?
If the template is declared in the same component that where it is used, @ViewChild
/ @ViewChildren
are working but it makes the component very less dynamic.如果模板是在使用它的同一个组件中声明的,
@ViewChild
/ @ViewChildren
正在工作,但它会使组件变得不那么动态。
I also tried using @ContentChildren
but it makes no difference.我也尝试过使用
@ContentChildren
但它没有区别。
I created a stackblitz in order to reproduce.我创建了一个堆栈闪电战以进行复制。 Here are some of the code:
以下是部分代码:
<ng-container #fromParent [ngTemplateOutlet]="template"></ng-container>
@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);
}
}
<ng-template #tmp> <hello name="{{ name }}"></hello> </ng-template>
<app-child [template]="tmp"> </app-child>
The log in child component returns false
.登录子组件返回
false
。
Here is the stackblitz: https://stackblitz.com/edit/angular-eopzyw?file=src/app/app.component.ts这是堆栈闪电战: https ://stackblitz.com/edit/angular-eopzyw ? file = src/app/app.component.ts
Thank you.谢谢你。
This is interesting, at first look, I too thought that it should be accessible, but did some debugging and found that:这很有趣,乍一看,我也以为应该是可以访问的,但是做了一些调试后发现:
The parent template is part of the parent component host view and hence the ViewChildren
in child component will not be able to access it as it is not the part of child component host view.父模板是父组件宿主视图的一部分,因此子组件中的
ViewChildren
将无法访问它,因为它不是子组件宿主视图的一部分。
Look at the below picture, app component has a host id 165 and the parent ng template gets associated with it.看下图,app 组件的主机 ID 为 165,父 ng 模板与之关联。
So it appears that in the current design of ViewChildren
it does not support querying the templates passed from a host view.所以看起来在当前的
ViewChildren
设计中,它不支持查询从宿主视图传递过来的模板。 May be opening a feature request will be a good idea.可能打开功能请求将是一个好主意。
Based on what @Ritesh Waghela discovered I found a way to get the views inside the template but is has some drawbacks.根据@Ritesh Waghela 的发现,我找到了一种在模板中获取视图的方法,但有一些缺点。
So because only the parent knows the existence of those views, it's his work to get their references.因为只有父级知道这些视图的存在,所以他的工作是获取它们的引用。
@ViewChildren(HelloComponent) public helloComponents = new QueryList<HelloComponent>();
The child will then get a reference to the parent thanks to Injector
.由于
Injector
,孩子将获得对父母的引用。
private parent: ParentComponent;
constructor(private injector: Injector) {
this.parent = injector.get<ParentComponent>(ParentComponent);
}
Because the @ViewChildren
of the parent will take all the HelloComponent
, in template or not, we need to differentiate them.因为父级的
@ViewChildren
会接受所有的HelloComponent
,无论是否在模板中,我们需要区分它们。 For this I did not find any better solution than adding an attribute inside HelloComponent
.为此,我没有找到比在
HelloComponent
添加属性更好的解决方案。
@Input() fromTemplate = false;
The parent component can distinguish HelloComponent
inside template or not:父组件可以区分模板内的
HelloComponent
与否:
<ng-template #tmp>
<hello name="inside template" fromTemplate="true"></hello>
</ng-template>
<hello name="outside template"></hello>
<app-child [template]="tmp"> </app-child>
The child component can now filter parent's views to get what it is searching for.子组件现在可以过滤父视图以获取它正在搜索的内容。
ngAfterViewInit() {
const viewFromTemplate = this.parent.helloComponents.filter(
(comp) => comp.fromTemplate
);
}
This solution is working but it has a few drawbacks:此解决方案有效,但有一些缺点:
The 1st drawback is not a huge issue in my case (it can be worked around because all of my components are contains inside a wrapper -> I take the reference to the known wrapper which can get a reference to the component it host).第一个缺点在我的情况下不是一个大问题(它可以解决,因为我的所有组件都包含在一个包装器中 - >我引用了已知的包装器,它可以获得对其托管的组件的引用)。
But the 2nd drawback seems more of an issue to me.但是第二个缺点对我来说似乎更像是一个问题。 Does anyone knows if a view can know weither it is part of a
ng-template
or not ?有谁知道一个视图是否可以知道它是否是
ng-template
一部分? I welcome any suggestion on this.我欢迎对此提出任何建议。
I created a stackblitz
to demonstrate my solution: https://angular-qgwcdf.stackblitz.io .我创建了一个
stackblitz
来演示我的解决方案: https : stackblitz
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.