简体   繁体   English

Angular 带有嵌套子项的内容投影

[英]Angular Content projection with nested children

StackBlitz Eample is here StackBlitz 示例在这里

I have a component where I would like the user to define there own template and then I want to pass that template to some nested children.我有一个组件,我希望用户在其中定义自己的模板,然后我想将该模板传递给一些嵌套的子级。 I'm having issues getting an instance of templates in the parent component.我在获取父组件中的模板实例时遇到问题。

I have my directive here我有我的指令在这里

@Directive({
  selector: '[customTemplate]',
})
export class CustomTemplate {
  public field!: string;

  constructor(public el: ElementRef) {}
}

I want to put this inside of a parent and get all instances of these directives.我想把它放在一个父对象中并获取这些指令的所有实例。

<div customTemplate field="test1">
  <ng-template myTemplate>
    <P>Some text here T1</P>
  </ng-template>
</div>
<div customTemplate field="test2">
  <ng-template myTemplate>
    <P>Some text here T2</P>
  </ng-template>
</div>

<Child1>
  <Child2>I'm going to render the ng-templates of myTemplate here</Child2>
</Child1>

In my Parent Component I have this在我的父组件中,我有这个

    @Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements AfterViewInit {
  @ContentChildren(CustomTemplate)
  public templates?: QueryList<CustomTemplate>;

  ngAfterViewInit(): void {
    console.log(this.templates);
    //here how do I get the instances of CustomTemplate
    
  }
}

The QueryList is empty查询列表为空在此处输入图像描述

I believe that content children might not be the right call.我相信满足的孩子可能不是正确的选择。 Using ViewChildren results in them being discovered.使用ViewChildren会导致他们被发现。 However, a few modifications need to be made.但是,需要进行一些修改。

Your selector in your directive is set as [customTemplate] .您的指令中的selector设置为[customTemplate] This is fine, however the selectors are case sensitive.这很好,但是选择器区分大小写。 Thus in your HTML when you use it as CustomTemplate it won't be discovered.因此,在您的 HTML 中,当您将其用作CustomTemplate时,它不会被发现。 Thus change your HTML to be either customTemplate or update your selector to have a capital C.因此,将您的 HTML 更改为 customTemplate 或更新您的选择器以具有大写字母 C。

Secondly, in order to do anything of value with said ViewChildren, as is mentioned here ( @ViewChildren Querylist Array is empty when children are rendered with *ngFor ) you need to subscribe to any changes that occur in your AfterViewInit其次,为了对所说的 ViewChildren 做任何有价值的事情,正如这里提到的( @ViewChildren Querylist Array 在使用 *ngFor 呈现子级时为空),您需要subscribe AfterViewInit中发生的任何更改

ex:前任:

this.templates.changes.subscribe((x) => console.log("From Change Sub: ", x));

Lastly, instead of trying to find the children using a string literal, pass in the actual class name instead as so:最后,不要尝试使用字符串文字来查找孩子,而是传递实际的 class 名称,如下所示:

@ViewChildren(CustomTemplate) instead of @ViewChildren('CustomTemplate') or @ViewChildren('customTemplate') @ViewChildren(CustomTemplate)而不是@ViewChildren('CustomTemplate')@ViewChildren('customTemplate')

The latter two do not work, the first one does.后两个不起作用,第一个起作用。 Also with the first one if you ever do decide to change the name of the class it will propagate throughout the app, and anywhere it did not the typechecker will find it.如果您确实决定更改 class 的名称,那么第一个也将在整个应用程序中传播,并且在没有类型检查器的任何地方都会找到它。

Updated stackblitz https://stackblitz.com/edit/angular-z5a8ae?file=src/app/app.component.html更新了 stackblitz https://stackblitz.com/edit/angular-z5a8ae?file=src/app/app.component.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM