基于类型的动态组件加载 angular
Dynamic component loading based on type angular
根据类型,我想在 angular 中渲染组件。
例如,使用下面的代码,我想动态渲染标题组件。
{
"type": "heading-1",
"text": "Sample Text"
}
下面是渲染动态组件的逻辑
private renderReactiveContent(content: ContentDocument, container: ViewContainerRef) {
// resolve content['_type'] to factory
const type: Type<any> = this.contentMappings[content[0].type];
if (!type) {
throw new ReferenceError(`No content mapping for type=${content[0].type}`);
}
const componentFactory: ComponentFactory<any> = this.componentFactoryResolver.resolveComponentFactory(type);
const component = container.createComponent(componentFactory, container.length, this.injector);
console.info('Component dynamically created ', component);
// content lifecycle hook: notify of new values
const cmpCreate: ContentOnCreate = asContentCreate(component);
cmpCreate.contentOnCreate(content);
// render embedded content
if (content && Object.keys(content).length > 0) {
const cmpEmbeddable: ContentEmbeddable = asContentEmbeddable(component);
if (cmpEmbeddable) {
// render in the target element of ContentEmbeddable
const childContainer = cmpEmbeddable.contentEmbeddable();
Object.keys(content).forEach((key: string) => {
const value = content[key];
// XX: recursive rendering
if (value instanceof Array) {
value.forEach((v: ContentDocument) => {
this.renderReactiveContent(v, childContainer);
});
} else {
this.renderReactiveContent(value, childContainer);
}
});
} else {
// fatal: embedded content must be hosted by ContentEmbeddable
const cmpName = component.instance['constructor'].name;
throw new TypeError([`Trying to render embedded content.`,
`${cmpName} must implement interface ContentEmbeddable`].join(' '));
}
}
component.hostView.detectChanges();
}
我不确定我做错了什么,它抛出了一个错误
ERROR TypeError: Trying to render embedded content. HeadlineComponent must implement interface ContentEmbeddable
我创建了 stackblitz,项目供参考,请帮忙。
首先,如错误所述,您的组件必须实现接口 ContentEmbeddable
。你可以这样做(对于你想要动态创建的每个组件):
import { Component, OnInit, Input, ViewContainerRef, ViewChild } from '@angular/core';
import { ContentOnCreate, ContentEmbeddable } from '../../render/content.interfaces';
@Component({
selector: 'rc-headline',
template: `<h1>{{ text }}</h1>`
})
export class HeadlineComponent implements OnInit, ContentOnCreate, ContentEmbeddable {
@Input()
public text: string;
constructor(private containerRef: ViewContainerRef) { }
ngOnInit() {
}
contentOnCreate(values: { [key: string]: any; }): void {
this.text = values.text;
}
contentEmbeddable(): ViewContainerRef {
return this.containerRef;
}
}
但项目仍然会抛出错误:
No content mapping for type=undefined
替换这个:
const type: Type<any> = this.contentMappings[content[0].type];
if (!type) {
throw new ReferenceError(`No content mapping for type=${content[0].type}`);
}
有了这个:
var type: Type<any>;
if (content instanceof Array) {
type = this.contentMappings[content[0].type];
} else {
type = this.contentMappings[content.type];
}
if (!type) {
return;
// throw new ReferenceError(`No content mapping for type=${type}`);
}
在 content-host.component.ts
文件中(renderReactiveContent
方法)将修复错误,您应该会看到示例标题和呈现的三个段落。
请参阅 StackBlitz 带有工作解决方案的演示。
根据类型,我想在 angular 中渲染组件。
例如,使用下面的代码,我想动态渲染标题组件。
{
"type": "heading-1",
"text": "Sample Text"
}
下面是渲染动态组件的逻辑
private renderReactiveContent(content: ContentDocument, container: ViewContainerRef) {
// resolve content['_type'] to factory
const type: Type<any> = this.contentMappings[content[0].type];
if (!type) {
throw new ReferenceError(`No content mapping for type=${content[0].type}`);
}
const componentFactory: ComponentFactory<any> = this.componentFactoryResolver.resolveComponentFactory(type);
const component = container.createComponent(componentFactory, container.length, this.injector);
console.info('Component dynamically created ', component);
// content lifecycle hook: notify of new values
const cmpCreate: ContentOnCreate = asContentCreate(component);
cmpCreate.contentOnCreate(content);
// render embedded content
if (content && Object.keys(content).length > 0) {
const cmpEmbeddable: ContentEmbeddable = asContentEmbeddable(component);
if (cmpEmbeddable) {
// render in the target element of ContentEmbeddable
const childContainer = cmpEmbeddable.contentEmbeddable();
Object.keys(content).forEach((key: string) => {
const value = content[key];
// XX: recursive rendering
if (value instanceof Array) {
value.forEach((v: ContentDocument) => {
this.renderReactiveContent(v, childContainer);
});
} else {
this.renderReactiveContent(value, childContainer);
}
});
} else {
// fatal: embedded content must be hosted by ContentEmbeddable
const cmpName = component.instance['constructor'].name;
throw new TypeError([`Trying to render embedded content.`,
`${cmpName} must implement interface ContentEmbeddable`].join(' '));
}
}
component.hostView.detectChanges();
}
我不确定我做错了什么,它抛出了一个错误
ERROR TypeError: Trying to render embedded content. HeadlineComponent must implement interface ContentEmbeddable
我创建了 stackblitz,项目供参考,请帮忙。
首先,如错误所述,您的组件必须实现接口 ContentEmbeddable
。你可以这样做(对于你想要动态创建的每个组件):
import { Component, OnInit, Input, ViewContainerRef, ViewChild } from '@angular/core';
import { ContentOnCreate, ContentEmbeddable } from '../../render/content.interfaces';
@Component({
selector: 'rc-headline',
template: `<h1>{{ text }}</h1>`
})
export class HeadlineComponent implements OnInit, ContentOnCreate, ContentEmbeddable {
@Input()
public text: string;
constructor(private containerRef: ViewContainerRef) { }
ngOnInit() {
}
contentOnCreate(values: { [key: string]: any; }): void {
this.text = values.text;
}
contentEmbeddable(): ViewContainerRef {
return this.containerRef;
}
}
但项目仍然会抛出错误:
No content mapping for type=undefined
替换这个:
const type: Type<any> = this.contentMappings[content[0].type];
if (!type) {
throw new ReferenceError(`No content mapping for type=${content[0].type}`);
}
有了这个:
var type: Type<any>;
if (content instanceof Array) {
type = this.contentMappings[content[0].type];
} else {
type = this.contentMappings[content.type];
}
if (!type) {
return;
// throw new ReferenceError(`No content mapping for type=${type}`);
}
在 content-host.component.ts
文件中(renderReactiveContent
方法)将修复错误,您应该会看到示例标题和呈现的三个段落。
请参阅 StackBlitz 带有工作解决方案的演示。