渲染 Angular 的 ContentChildren 中的组件

问题描述 投票:0回答:3

这是我的组件:

import { Component, OnInit, ContentChildren, QueryList } from '@angular/core';
import { IconBoxComponent } from '../icon-box/icon-box.component';

@Component({
  selector: 'app-three-icon-box',
  templateUrl: './three-icon-box.component.html',
  styleUrls: ['./three-icon-box.component.scss']
})
export class ThreeIconBoxComponent implements OnInit {
  @ContentChildren(IconBoxComponent) boxes: QueryList<IconBoxComponent>;

  constructor() { }

  ngOnInit() {
  }

  ngAfterContentInit() {
    console.log(this.boxes);
  }

}

它的模板看起来像这样:

<div class="row justify-content-center">
  <div class="col-12 col-md-10">
    <div class="row justify-content-center text-center">
      <div *ngFor="let box of boxes" class="col-12 col-sm-4 col-lg-3 offset-lg-1 lz-mb-2 lz-mb-sm-0">
        {{ box }}
      </div>
    </div>
  </div>
</div>

这就是我渲染它的方式:

  <app-three-icon-box>
    <app-icon-box icon="#icon-one">content 1</app-icon-box>
    <app-icon-box icon="#icon-two">content 2</app-icon-box>
    <app-icon-box icon="#icon-three">content 3</app-icon-box>
  </app-three-icon-box>

在第二个代码块中,我试图渲染

<app-icon-box>
,但我不知道如何渲染。
{{ box }}
只是我想做的事情的一个想法,但我只是得到了
[object Object]

angular typescript components
3个回答
20
投票

你应该使用这个模式

  1. 创建 TemplateMarker 指令来标记要作为参数传递的 templates(以防止抓取 其他模板)。
  2. 使用
    @ContentChildren
    注入标记。
  3. 使用 NgTemplateOutlet 将它们渲染到您需要的位置。

提示:您可以多次渲染每个模板并向它们发送参数

示例:

import { Component, Input, Directive, TemplateRef, ContentChildren, QueryList } from '@angular/core';
@Directive({
  selector: '[templateMarker]'
})
export class TemplateMarker {
  constructor(public template: TemplateRef<any>) {}
}
@Component({
  selector: 'template-owner',
  template: `
    <div *ngFor="let marker of markers">
      <i><ng-template [ngTemplateOutlet]="marker.template"></ng-template></i>
    </div>
  `,
})
export class TemplateOwner {
  @ContentChildren(TemplateMarker) markers: QueryList<TemplateMarker>;
}
@Component({
  selector: 'hello',
  template: `<template-owner>
    <div *templateMarker>first template</div>
    <div *templateMarker>second template</div>
  </template-owner>`,
})
export class HelloComponent  {}

14
投票

有点不清楚你需要什么。 但我想使用 ng-content 就足够了。删除 ContentChildren 和 ngFor 并使用

<ng-content></ng-content>

在您的模板中。

然后您必须直接在声明盒子组件的位置添加类。

<app-icon-box class="col-12 col-sm-4 col-lg-3 offset-lg-1 lz-mb-2 lz-mb-sm-0" icon="#here-to-help-you">

为了丰富 ThreeIconBoxComponent 中的投影组件,您将需要使用模板和模板出口的完全不同的方法。


0
投票

这是一个老问题,但我只是在我正在开发的应用程序中问同样的问题。

我不确定我的解决方案有多“正确”,但这就是我解决这个问题的方法。

就我而言,我的父母

component
只应该接受特定类型的内容(在您的情况下,这将是
IconBoxComponent
)。

在该子项

component
(此处为
IconBoxComponent
)中,我暴露了一个
TemplateRef
,然后父级
component
可以使用它进行渲染。

虽然使用

directive
也有效,但我不喜欢必须使用我的自定义子
component
以及自定义
directive
的想法。

注意:在下面的示例中,我删除了所有

CSS
classes
和一些
HTML
元素,以使其更具可读性。由于某些技术原因,它们没有被删除。

图标框组件

@Component({
  selector: 'app-icon-box',
  template: `
    <ng-template #template>
       <span>My Icon Box</span>
    </ng-template>
  `,
   styleUrls: ['./icon-box.component.scss']
})
export class IconBoxComponent {
  @ViewChild('template', { static: true }) template!: TemplateRef<any>;
}

ThreeIconBox组件


@Component({
  selector: 'app-three-icon-box',
  template: `
     <div>
       <div *ngFor="let box of boxes">
         <ng-container
           [ngTemplateOutlet]="box.template"
         ></ng-container>
       </div>
      </div>
  `,
  styleUrls: ['./three-icon-box.component.scss']
})
export class ThreeIconBoxComponent {
  @ContentChildren(IconBoxComponent) boxes = new QueryList<IconBoxComponent>();
}

使用方法

<app-three-icon-box>
  <app-icon-box>content 1</app-icon-box>
  <app-icon-box>content 2</app-icon-box>
  <app-icon-box>content 3</app-icon-box>
</app-three-icon-box>
© www.soinside.com 2019 - 2024. All rights reserved.