Angular: 从变量渲染组件
Angular: Render component from variable
在我的组件中,我有一个通过 @ContentChildren
收到的组件列表。现在我想在我的视图中呈现这些组件,但我不知道如何这样做。我尝试了 ng-container
和 ng-content
,但没有成功。我在想一些事情:
<component-renderer [component]="myComponent"></component-renderer>
但我还没有找到任何提供此功能的东西。我整理了一个完整的(尽可能少的)示例来获得图片(也许我之前已经出错了?)。在我的组件中获取对这些组件的引用也很重要,因为它们都将实现我想要使用的特定接口:
MyInterface.ts
import { InjectionToken } from "@angular/core";
export const MyInterfaceToken = new InjectionToken<MyInterface>('MyInterfaceToken');
// This interface will be implemented by the "child" components.
export interface MyInterface {
doSomething(): void;
}
simple.component.ts
import { Component, OnInit, Input, forwardRef } from '@angular/core';
import { MyInterface, MyInterfaceToken } from '../MyInterface';
@Component({
selector: 'app-simple',
template: '<div>{{ value }}</div>',
providers: [{
provide: MyInterfaceToken, useExisting: SimpleComponent
}]
})
export class SimpleComponent implements MyInterface {
@Input() public value: string;
doSomething(): void {
alert(this.value);
}
}
多container.component.ts
import { Component, OnInit, Self, Inject, Optional, Directive, ContentChildren, AfterContentInit, QueryList } from '@angular/core';
import { MyInterface, MyInterfaceToken } from '../MyInterface';
// Directive to retreive the components, partially taken from:
// https://github.com/angular/angular/issues/8277
@Directive({ selector: '[multi-container-item]' })
export class MultiContainerItemDirective {
constructor(@Inject(MyInterfaceToken) @Self() @Optional() public component: MyInterface) {}
}
@Component({
selector: 'app-multi-container',
templateUrl: './multi-container.component.html'
})
export class MultiContainerComponent implements AfterContentInit {
@ContentChildren(MultiContainerItemDirective) public items: QueryList<MultiContainerItemDirective>;
public ngAfterContentInit() {
console.log(this.items); // Inspect in console => got both items.
this.items.first.component.doSomething(); // works.
}
public getComponents() {
return this.items.map(x => x.component);
}
}
用法示例
<app-multi-container>
<app-simple [value]="'Test1'" multi-container-item></app-simple>
<app-simple [value]="'Test2'" multi-container-item></app-simple>
</app-multi-container>
简而言之:我将什么放入多容器的 html 中以呈现项目?类似于:
<div *ngFor="let component of getComponents()">
<component-renderer [component]="component"></component-renderer>
</div>
您可以简单地在 MultiContainerComponent
组件中使用 ng-content
:
<div><ng-content select="[multi-container-item]"></ng-content></div>
在我的组件中,我有一个通过 @ContentChildren
收到的组件列表。现在我想在我的视图中呈现这些组件,但我不知道如何这样做。我尝试了 ng-container
和 ng-content
,但没有成功。我在想一些事情:
<component-renderer [component]="myComponent"></component-renderer>
但我还没有找到任何提供此功能的东西。我整理了一个完整的(尽可能少的)示例来获得图片(也许我之前已经出错了?)。在我的组件中获取对这些组件的引用也很重要,因为它们都将实现我想要使用的特定接口:
MyInterface.ts
import { InjectionToken } from "@angular/core";
export const MyInterfaceToken = new InjectionToken<MyInterface>('MyInterfaceToken');
// This interface will be implemented by the "child" components.
export interface MyInterface {
doSomething(): void;
}
simple.component.ts
import { Component, OnInit, Input, forwardRef } from '@angular/core';
import { MyInterface, MyInterfaceToken } from '../MyInterface';
@Component({
selector: 'app-simple',
template: '<div>{{ value }}</div>',
providers: [{
provide: MyInterfaceToken, useExisting: SimpleComponent
}]
})
export class SimpleComponent implements MyInterface {
@Input() public value: string;
doSomething(): void {
alert(this.value);
}
}
多container.component.ts
import { Component, OnInit, Self, Inject, Optional, Directive, ContentChildren, AfterContentInit, QueryList } from '@angular/core';
import { MyInterface, MyInterfaceToken } from '../MyInterface';
// Directive to retreive the components, partially taken from:
// https://github.com/angular/angular/issues/8277
@Directive({ selector: '[multi-container-item]' })
export class MultiContainerItemDirective {
constructor(@Inject(MyInterfaceToken) @Self() @Optional() public component: MyInterface) {}
}
@Component({
selector: 'app-multi-container',
templateUrl: './multi-container.component.html'
})
export class MultiContainerComponent implements AfterContentInit {
@ContentChildren(MultiContainerItemDirective) public items: QueryList<MultiContainerItemDirective>;
public ngAfterContentInit() {
console.log(this.items); // Inspect in console => got both items.
this.items.first.component.doSomething(); // works.
}
public getComponents() {
return this.items.map(x => x.component);
}
}
用法示例
<app-multi-container>
<app-simple [value]="'Test1'" multi-container-item></app-simple>
<app-simple [value]="'Test2'" multi-container-item></app-simple>
</app-multi-container>
简而言之:我将什么放入多容器的 html 中以呈现项目?类似于:
<div *ngFor="let component of getComponents()">
<component-renderer [component]="component"></component-renderer>
</div>
您可以简单地在 MultiContainerComponent
组件中使用 ng-content
:
<div><ng-content select="[multi-container-item]"></ng-content></div>