重用动态加载的组件时出错 [英] Error While Reusing Component That Have Been Loaded On The fly

查看:21
本文介绍了重用动态加载的组件时出错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个组件,该组件使用来自我的服务器的模板动态加载子组件,如本主题

I Have created a component that load on the fly a child component with a template which are comming from my server like this topic

在 Angular 4/5 中编译动态 HTML - 类似于 Angular JS 中的 $compile

我想从我的应用程序的任何地方调用这个组件,它的选择器可以从模态模板中调用(我不能多次重新加载模态),它可能会从浏览器调用(我不能同时加载模态和浏览器)

I Would like to call this component from anywhere in my application, Its selector may be called from a modal template (I cannot reload the modal multiple time), It may be called from the browser (And I cannot load both modal and browser in the same time)

@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();
    }
  }
}

但是当这部分重新加载时(不刷新浏览器)我有这个错误:

But when this part are reloadded (without refreshing the browser) I Have this error :

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)

推荐答案

由于要动态渲染的组件需要在组件中导入,并且需要注册到同一个组件父模块中.

Since the component which you wants to render dynamically needs to be imported in the component and needs to be registered in the same components parent module.

如果您想从其他应用程序位置使用相同的组件,它会导致很少的问题,这些问题几乎没有解决方法.您可以按照以下文章了解更多信息,https://blog.angularindepth.com/here-is-you-need-to-know-about-dynamic-components-in-angular-ac1e96167f9e

If you want to use the same component from some other place of application it causes few issues, which have few workarounds on them. You can follow below article to learn more on same, https://blog.angularindepth.com/here-is-what-you-need-to-know-about-dynamic-components-in-angular-ac1e96167f9e

但是过程变得相当复杂,我强烈建议您使用可以新添加到 angular CDK 的门户,门户是可以动态呈现到页面上的开放插槽的一段 UI.UI 部分"可以是 Component 或 TemplateRef,而open slot"是 PortalHost.

But the process becomes quite complicated, I will highly recommend you using portals which can be newly added to angular CDK, A Portal is a piece of UI that can be dynamically rendered to an open slot on the page. The "piece of UI" can be either a Component or a TemplateRef and the "open slot" is a PortalHost.

有一个很好的演示视频.

There is a nice presentational video on same.

https://www.youtube.com/watch?v=YQMIR01dQew

希望这会有所帮助,祝您一切顺利!!

Hope this helps, All the Best!!

这篇关于重用动态加载的组件时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆