3

我有一个子组件,它接受 aTemplateRef作为@Input并通过ngTemplateOutlet. 如何使用@ViewChild/@ViewChildren检索模板内的组件?

如果模板在使用它的同一组件中声明,则@ViewChild/@ViewChildren正在工作,但它会使组件的动态性降低。

我也尝试过使用@ContentChildren,但没有区别。

我创建了一个 stackblitz 来重现。以下是一些代码:

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);
  }
}
父组件.html
<ng-template #tmp> <hello name="{{ name }}"></hello> </ng-template>
<app-child [template]="tmp"> </app-child>

登录子组件返回false.

这是堆栈闪电战:https ://stackblitz.com/edit/angular-eopzyw?file=src/app/app.component.ts

谢谢你。

4

2 回答 2

3

这个很有意思,乍一看,我也觉得应该可以访问,但是做了一些调试发现:

父模板是父组件宿主视图的一部分,因此ViewChildren子组件将无法访问它,因为它不是子组件宿主视图的一部分。

看下图,app 组件的主机 id 为 165,父 ng 模板与之关联。

在此处输入图像描述

因此,在当前的设计中,ViewChildren它似乎不支持查询从主机视图传递的模板。可能打开功能请求将是一个好主意。

于 2021-10-25T16:05:21.420 回答
0

根据@Ritesh Waghela 的发现,我找到了一种在模板中获取视图的方法,但它有一些缺点。


所以因为只有父母知道这些观点的存在,所以他的工作是获得他们的参考。

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

然后,孩子将获得对父母的引用,感谢Injector.

child.component.ts
private parent: ParentComponent;
constructor(private injector: Injector) {
   this.parent = injector.get<ParentComponent>(ParentComponent);
}

因为无论是否在模板@ViewChildren中,父级的HelloComponent,我们都需要区分它们。为此,我没有找到比在内部添加属性更好的解决方案HelloComponent

你好.component.ts
@Input() fromTemplate = false;

父组件可以区分HelloComponent是否在模板内部:

父组件.html
<ng-template #tmp> 
  <hello name="inside template" fromTemplate="true"></hello>
</ng-template>

<hello name="outside template"></hello>
<app-child [template]="tmp"> </app-child>

子组件现在可以过滤父视图以获取它正在搜索的内容。

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

此解决方案有效,但有一些缺点:

  • 孩子必须知道其父母的类型;
  • 父级必须将模板内的每个视图声明为“来自模板的视图”;

第一个缺点在我的情况下不是一个大问题(它可以解决,因为我的所有组件都包含在一个包装器中 -> 我引用了已知的包装器,它可以获取对它托管的组件的引用)。

但第二个缺点对我来说似乎更成问题。有谁知道一个视图是否可以知道它是否是 a 的一部分ng-template?我欢迎对此提出任何建议。


我创建了一个stackblitz来演示我的解决方案:https ://angular-qgwcdf.stackblitz.io 。

于 2021-10-27T06:41:35.587 回答