我已经创建了一个组件,该组件可以动态加载带有模板的子组件,该子组件是从我的服务器发出的,就像本主题一样
Compile dynamic HTML in Angular 4/5- something similar to $compile in Angular JS
我想从应用程序中的任何位置调用此组件,它的选择器可以从模式模板中调用( 我无法多次重新加载模式 ),可以从浏览器中调用( 并且我无法同时加载模式和浏览器 )
@Component({
selector: 'my-component',
template: `<h2>Stuff bellow will get dynamically created and injected<h2>
<div #vc></div>`
})
export class TaggedDescComponent {
@ViewChild('vc', {read: ViewContainerRef}) vc: ViewContainerRef;
private cmpRef: ComponentRef<any>;
constructor(private compiler: Compiler,
private injector: Injector,
private moduleRef: NgModuleRef<any>,
private backendService: backendService,
) {}
ngAfterViewInit() {
// Here, get your HTML from backend.
this.backendService.getHTMLFromServer()
.subscribe(rawHTML => this.createComponentFromRaw(rawHTML));
}
// Here we create the component.
private createComponentFromRaw(template: string) {
// Let's say your template looks like `<h2><some-component [data]="data"></some-component>`
// As you see, it has an (existing) angular component `some-component` and it injects it [data]
// Now we create a new component. It has that template, and we can even give it data.
const tmpCmp = Component({ template, styles })(class {
// the class is anonymous. But it's a quite regular angular class. You could add @Inputs,
// @Outputs, inject stuff etc.
data: { some: 'data'};
ngOnInit() { /* do stuff here in the dynamic component */}
});
// Now, also create a dynamic module.
const tmpModule = NgModule({
imports: [RouterModule],
declarations: [tmpCmp],
// providers: [] - e.g. if your dynamic component needs any service, provide it here.
})(class {});
// Now compile this module and component, and inject it into that #vc in your current component template.
this.compiler.compileModuleAndAllComponentsAsync(tmpModule)
.then((factories) => {
const f = factories.componentFactories[0];
this.cmpRef = f.create(this.injector, [], null, this.moduleRef);
this.cmpRef.instance.name = 'my-dynamic-component';
this.vc.insert(this.cmpRef.hostView);
});
}
// Cleanup properly. You can add more cleanup-related stuff here.
ngOnDestroy() {
if(this.cmpRef) {
this.cmpRef.destroy();
}
}
}
但是当重新加载此部分(不刷新浏览器)时,我出现此错误:
ERROR Error: Type e is part of the declarations of 2 modules: function(){} and function(){}! Please consider moving e to a higher module that imports function(){} and function(){}. You can also create a new NgModule that exports and includes e then import that NgModule in function(){} and function(){}.
at le (main.js:1)
at e._addTypeToModule (main.js:1)
at main.js:1
at Array.forEach (<anonymous>)
at e.getNgModuleMetadata (main.js:1)
at e._loadModules (main.js:1)
at e._compileModuleAndAllComponents (main.js:1)
at e.compileModuleAndAllComponentsAsync (main.js:1)
at e.compileModuleAndAllComponentsAsync (main.js:1)
at e.createComponentFromRaw (main.js:1)
答案 0 :(得分:0)
因为要动态渲染的组件需要导入到组件中,并且需要在相同的组件父模块中注册。
如果要在其他应用程序中使用同一组件,则不会引起什么问题,也没有解决方法。 您可以关注以下文章,以了解更多相关信息, https://blog.angularindepth.com/here-is-what-you-need-to-know-about-dynamic-components-in-angular-ac1e96167f9e
但是过程变得非常复杂,我强烈建议您使用可以新添加到有角CDK的门户, 门户是可以动态呈现到页面上的空白位置的一部分UI。 “ UI部分”可以是Component或TemplateRef,“开放插槽”可以是PortalHost。
在同一段视频上有一个不错的演示视频。
https://www.youtube.com/watch?v=YQMIR01dQew
希望这对您有所帮助!