简体   繁体   English

来自父组件的 ngTemplateOutlet 的 ViewChild

[英]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:以下是部分代码:

child.component.html子组件.html
<ng-container #fromParent [ngTemplateOutlet]="template"></ng-container>
child.component.ts子组件.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父组件.html
<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.因为只有父级知道这些视图的存在,所以他的工作是获取它们的引用。

parent.component.ts父组件.ts
@ViewChildren(HelloComponent) public helloComponents = new QueryList<HelloComponent>();

The child will then get a reference to the parent thanks to Injector .由于Injector ,孩子将获得对父母的引用。

child.component.ts子组件.ts
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添加属性更好的解决方案。

hello.component.ts hello.component.ts
@Input() fromTemplate = false;

The parent component can distinguish HelloComponent inside template or not:父组件可以区分模板内的HelloComponent与否:

parent.component.html父组件.html
<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.子组件现在可以过滤父视图以获取它正在搜索的内容。

child.component.ts子组件.ts
ngAfterViewInit() {
  const viewFromTemplate = this.parent.helloComponents.filter(
    (comp) => comp.fromTemplate
  );
}

This solution is working but it has a few drawbacks:此解决方案有效,但有一些缺点:

  • The child must know the type of its parent;孩子必须知道其父母的类型;
  • The parent must declare each view inside the template as being a "view from template";父级必须将模板内的每个视图声明为“来自模板的视图”;

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.

相关问题 来自@ViewChild的属性不会在父组件中更新 - Property from @ViewChild does not update in Parent Component 使用来自 Parent 的 ViewChild 访问嵌套在 ngTemplate 中的组件 - Access component nested in ngTemplate with ViewChild from Parent ViewChild 在从子组件返回到父组件时返回 undefined - ViewChild returns undefined while returning from child component to parent component 来自另一个组件的@ViewChild() - @ViewChild() from another component angular 2从@ViewChild组件重新渲染父组件 - angular 2 re-render parent component from @ViewChild Component 将数据从子组件传递到 Angular 中的父组件 @ViewChild 预期 2 个参数 - Pass data from child component to parent component in Angular @ViewChild Expected 2 arguments Angular 8:在子组件中调用该方法后,使用 ViewChild 获取从子组件到父组件的方法结果 - Angular 8: using ViewChild get a method result from a child to parent after that method is invoked in child component angular的@input vs viewchild用于从父组件发送数据到子组件 - angular's @input vs viewchild for sending data from parent to child component 如何在不使用 angular 中的 @viewChild 的情况下从父组件调用子组件的 function? - How to call child component's function from parent without use of @viewChild in angular? 如何在父组件(Angular)中操作来自子组件的数据? - How to manipulate data coming from child component in parent component (Angular)?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM