在Angular中,如何对children列表做Content Projection?
In Angular, how to do Content Projection over the list of children?
我有一个组件应该接受 任意数量 的已知类型的子组件,并在 *ngFor
中使用额外的包装器呈现它们。或者,我可以传递并呈现 <ng-template>
的列表吗?
容器将这样使用:
<app-custom-container>
<app-custom-child name="1">...</app-custom-child>
<app-custom-child name="2">...</app-custom-child>
<app-custom-child name="3">...</app-custom-child>
</app-custom-container>
内部容器模板我想做这样的事情:
template: '<div>
<ng-container *ngFor="let child of ...?">
<app-custom-child-internal-wrapper [id]="child.id">
<ng-content/> <!--somehow only render this specific child-->
</app-custom-child-internal-wrapper>
</ng-content>
</div>'
可以做这个或类似的事情吗?
解决了。您可以仅将 CustomChildComponent
用于模板,如果使用 @ContentChildren(CustomChildComponent)
则获取列表
用法:
<app-custom-container>
<app-custom-child name="1">
<ng-template #innertemplate>
...
</ng-temlate>
</app-custom-child>
<app-custom-child name="2">
<ng-template #innertemplate>
...
</ng-temlate>
</app-custom-child>
</app-custom-container>
子组件:
@Component({
selector: 'app-custom-child',
template: '', // template empty by design
})
export class CustomChildComponent {
@Input() public name!: string;
@ContentChild('innertemplate', { read: TemplateRef })
public innerTemplateReference!: TemplateRef<any>;
}
父组件:
@Component({
selector: 'app-custom-container',
template: '<app-some-internal-container>
<ng-container *ngFor="let child of contentChildren">
<app-some-internal-wrapper>
<ng-container ngTemplateOutlet="child.innerTemplateReference">
</ng-container>
</app-some-internal-wrapper>
</ng-container>
</app-some-internal-container>',
})
export class CustomContainerComponent {
@ContentChildren(CustomChildComponent)
public contentChildren: QueryList<CustomChildComponent>;
}
这是 ContentChildren
和 ngTemplateOutlet
的用例...就像这样
首先你需要一个指令来标记和获取任何你想要呈现的 children 的模板引用:
@Directive({ selector: '[childMarker]'})
export class ChildMarkerDirective {
constructor(public templateRef: TemplateRef<any>) { }
}
然后将其添加到 children:
<app-custom-container>
<app-custom-child *childMarker name="1">...</app-custom-child>
<app-custom-child *childMarker name="2">...</app-custom-child>
<app-custom-child *childMarker name="3">...</app-custom-child>
</app-custom-container>
在您的自定义容器控制器中,您需要这样的东西来查询内容中的标记:
@ContentChildren(ChildMarkerDirective)
children
然后在您的模板中,您可以迭代和投影:
<div>
<ng-container *ngFor="let child of children">
<app-custom-child-internal-wrapper>
<ng-container *ngTemplateOutlet="child.templateRef"></ng-container>
</app-custom-child-internal-wrapper>
</ng-content>
</div>
我有一个组件应该接受 任意数量 的已知类型的子组件,并在 *ngFor
中使用额外的包装器呈现它们。或者,我可以传递并呈现 <ng-template>
的列表吗?
容器将这样使用:
<app-custom-container>
<app-custom-child name="1">...</app-custom-child>
<app-custom-child name="2">...</app-custom-child>
<app-custom-child name="3">...</app-custom-child>
</app-custom-container>
内部容器模板我想做这样的事情:
template: '<div>
<ng-container *ngFor="let child of ...?">
<app-custom-child-internal-wrapper [id]="child.id">
<ng-content/> <!--somehow only render this specific child-->
</app-custom-child-internal-wrapper>
</ng-content>
</div>'
可以做这个或类似的事情吗?
解决了。您可以仅将 CustomChildComponent
用于模板,如果使用 @ContentChildren(CustomChildComponent)
用法:
<app-custom-container>
<app-custom-child name="1">
<ng-template #innertemplate>
...
</ng-temlate>
</app-custom-child>
<app-custom-child name="2">
<ng-template #innertemplate>
...
</ng-temlate>
</app-custom-child>
</app-custom-container>
子组件:
@Component({
selector: 'app-custom-child',
template: '', // template empty by design
})
export class CustomChildComponent {
@Input() public name!: string;
@ContentChild('innertemplate', { read: TemplateRef })
public innerTemplateReference!: TemplateRef<any>;
}
父组件:
@Component({
selector: 'app-custom-container',
template: '<app-some-internal-container>
<ng-container *ngFor="let child of contentChildren">
<app-some-internal-wrapper>
<ng-container ngTemplateOutlet="child.innerTemplateReference">
</ng-container>
</app-some-internal-wrapper>
</ng-container>
</app-some-internal-container>',
})
export class CustomContainerComponent {
@ContentChildren(CustomChildComponent)
public contentChildren: QueryList<CustomChildComponent>;
}
这是 ContentChildren
和 ngTemplateOutlet
的用例...就像这样
首先你需要一个指令来标记和获取任何你想要呈现的 children 的模板引用:
@Directive({ selector: '[childMarker]'})
export class ChildMarkerDirective {
constructor(public templateRef: TemplateRef<any>) { }
}
然后将其添加到 children:
<app-custom-container>
<app-custom-child *childMarker name="1">...</app-custom-child>
<app-custom-child *childMarker name="2">...</app-custom-child>
<app-custom-child *childMarker name="3">...</app-custom-child>
</app-custom-container>
在您的自定义容器控制器中,您需要这样的东西来查询内容中的标记:
@ContentChildren(ChildMarkerDirective)
children
然后在您的模板中,您可以迭代和投影:
<div>
<ng-container *ngFor="let child of children">
<app-custom-child-internal-wrapper>
<ng-container *ngTemplateOutlet="child.templateRef"></ng-container>
</app-custom-child-internal-wrapper>
</ng-content>
</div>