Angular将动态入口组件传递到模块中,然后再将它们传递到另一个模块中

时间:2018-03-26 20:22:01

标签: javascript angular

我正在为组件库制作模态组件。我制作了第三方模态库,我在我的组件库中使用它。一个主要功能是能够通过服务传递组件并将其动态添加到模式中。

我的modal lib有一个静态方法,允许您将组件添加到模块的条目组件中。它看起来像:

export class A11yModalModule {
  static withComponents(components: any[]) {
    return {
      ngModule: A11yModalModule,
      providers: [{
        provide: ANALYZE_FOR_ENTRY_COMPONENTS,
        useValue: components,
        multi: true
      }]
    };
  }
}

很酷,这很有效。当我导入模块时,我可以将组件传递给它:A11yModalModule.withComponents([ModalContentComponent])

当我把它抽象出另一个层次时,我的问题就出现了。所以现在不是2个模块,而是3个。我需要像上面那样从lib使用者模块传递一个组件到我的组件模块,然后传递到模态模块。

如何将组件从lib模块传递到模态模块?

我想我已经接近了。这是我的3个模块

// app module
@NgModule({
  declarations: [AppComponent, ModalContentComponent],
  imports: [
    LibModalModule.withComponents([ModalContentComponent])
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }



// lib module
@NgModule({
  imports: [CommonModule],
  declarations: [LibModal],
  providers: [LibModalService],
  exports: []
})
export class LibModalModule {
  static withComponents(components: any[]) {
    return {
      ngModule: LibModalModule,
      imports: [CommonModule, A11yModalModule.withComponents(components)]
    };
  }
}



// a11y modal module
@NgModule({
  imports: [CommonModule],
  declarations: [ModalComponent],
  exports: [],
  providers: [ModalService, DomService],
  entryComponents: [ModalComponent]
})
export class A11yModalModule {
  static withComponents(components: any[]) {
    return {
      ngModule: A11yModalModule,
      providers: [{
        provide: ANALYZE_FOR_ENTRY_COMPONENTS,
        useValue: components,
        multi: true
      }]
    };
  }
}

2 个答案:

答案 0 :(得分:4)

withComponents方法应该返回ModuleWithProviders对象,它只是包含提供程序的模块的包装器。

它不能具有imports属性或其他内容,因为它不了解这些属性。这是来自角度源代码的excerpt,负责从ModuleWithProviders读取元数据:

else if (importedType && importedType.ngModule) {
  const moduleWithProviders: ModuleWithProviders = importedType;
  importedModuleType = moduleWithProviders.ngModule;
  if (moduleWithProviders.providers) {
    providers.push(...this._getProvidersMetadata(
        moduleWithProviders.providers, entryComponents,
        `provider for the NgModule '${stringifyType(importedModuleType)}'`, [],
            importedType));
    }
}

我们可以看到角度编译器从withComponents方法返回的对象中获取提供者。

因此,为了合并您的模块,您可以使用您的方法(在ANALYZE_FOR_ENTRY_COMPONENTS中提供LibModalModule.withProviders)或重用A11yModalModule.withComponents,如:

@NgModule({
  imports: [CommonModule, A11yModalModule],
  providers: [LibModalService],
  exports: []
})
export class LibModalModule {
  static withComponents(components: any[]) {
    return {
      ngModule: LibModalModule,
      providers: A11yModalModule.withComponents(components).providers
    };
  }
}

(经AOT测试)

如果我们希望将其提供程序包含在我们的根模块注入器中,则必须在A11yModalModule中导入LibModalModule(我想您将使用ModalService和{{ 1}}在DomService)中被解析。这样做的原因是angular包括根模块注入器中传递模块的所有提供者。

另见:

答案 1 :(得分:0)

我有一个给我一个假旗的错误。事实证明,您只需将相同的withComponents方法添加到组件库模块,它就可以通过组件。如果有人知道,我会喜欢解释它是如何工作的。

// app module
@NgModule({
  declarations: [AppComponent, ModalContentComponent],
  imports: [
    LibModalModule.withComponents([ModalContentComponent])
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }



// lib module
@NgModule({
  imports: [CommonModule, A11yModalModule],
  declarations: [LibModal],
  providers: [LibModalService],
  exports: []
})
export class LibModalModule {
  static withComponents(components: any[]) {
    return {
      ngModule: LibModalModule,
      providers: [{
        provide: ANALYZE_FOR_ENTRY_COMPONENTS,
        useValue: components,
        multi: true
      }]
    };
  }
}



// a11y modal module
@NgModule({
  imports: [CommonModule],
  declarations: [ModalComponent],
  exports: [],
  providers: [ModalService, DomService],
  entryComponents: [ModalComponent]
})
export class A11yModalModule {
  static withComponents(components: any[]) {
    return {
      ngModule: A11yModalModule,
      providers: [{
        provide: ANALYZE_FOR_ENTRY_COMPONENTS,
        useValue: components,
        multi: true
      }]
    };
  }
}