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

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

问题描述

我已经创建了一个组件,该组件可动态加载带有模板的子组件,该子组件是从我的服务器(如本主题)中来的

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

我想从我的应用程序中的任何地方调用此组件,它的选择器可以从模式模板中调用( 我无法多次重新加载模式 ),可以从浏览器中调用( 并且我无法同时加载模式和浏览器 )

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/此处是您需要了解什么有关ac-ac1e96167f9e-dynamic-components的信息

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

但是过程变得非常复杂,我强烈建议您使用可以新添加到有角CDK的门户, 门户是可以动态呈现到页面上的空白位置的一部分UI. "UI部分"可以是Component或TemplateRef,开放插槽"可以是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

希望这对您有所帮助!

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

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