用Ag-grid在Angular中加载动态模块的问题

时间:2018-07-26 09:44:59

标签: angular angular5 angular-cli ag-grid ag-grid-ng2

我们是Ag-Grid Enterprise的使用者之一,我们围绕ag-grid编写了包装网格,以根据我们公司的规范添加自定义功能,逻辑和可重用性,并作为节点模块发布。

我们现在要解决的主要要求之一是动态接收由使用者(在其项目中定义)构建的组件,将其馈送到包装器网格,并以预期的方式内部馈送到ag-grid

下面的代码段对其进行了详细说明。

消费类应用程序/ AppModule.ts

  1. 下面的代码片段是一个消费者项目AppModule.ts,他们在其中使用ParentModule.forRoot(manifest)导入我们的库。清单是其组成部分的路由数组。

  2. 清单对象具有3个属性-componentId,path和loadChildren,这些属性特定于消费者应用程序中的组件。清单中可以有多个对象指向不同的组件。

const manifests: DynamicComponentManifest[] = [
  {
    componentId: 'message-icon',
    path: 'dynamic-message-icon-editors', // some globally-unique identifier, used internally by the router
    loadChildren: './dynamic-modules/message/message.module#MessageModule',
  }
];


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    FormsModule,
    ReactiveFormsModule,
    ParentModule.forRoot(manifests),
  ]
})

库/ ParentModule.ts

  1. 然后在我们库的forRoot静态方法中读取清单,以便解析路由,DynamicComponentLoader服务和DYNAMIC_COMPONENT_MANIFEST InjectionToken。
  2. ParentModule也会导入gridModule,后者会导入AG-GRID模块。

@NgModule({
    imports: [
        CommonModule,
        HttpClientModule,
        gridModule  // grid module is where Ag-grid is used
    ],
    exports: [ParentComponent],
    declarations: [ParentComponent],
    providers: [ParentComponentService, CommonServices, GRIDCONFIG],
    bootstrap: [ParentComponent]

})

export class ParentModule {
    constructor(){}
    static forRoot(manifests: DynamicComponentManifest[]): ModuleWithProviders {

        return {
            ngModule: ParentModule,
            providers: [
                DynamicComponentLoader,
                { provide: NgModuleFactoryLoader, useClass: SystemJsNgModuleLoader },
                // provider for Angular CLI to analyze
                { provide: ROUTES, useValue: manifests, multi: true },
                // provider for DynamicComponentLoader to analyze
                { provide: DYNAMIC_COMPONENT_MANIFESTS, useValue: manifests },
            ],
        };
    }
}

库/ DynamicComponentLoader.ts

  • 这是获取组件工厂的服务调用

import { DYNAMIC_COMPONENT, DYNAMIC_COMPONENT_MANIFESTS, DynamicComponentManifest } from './dynamic-component-manifest';
    
    export class DynamicComponentLoader {
        constructor(
        @Inject(DYNAMIC_COMPONENT_MANIFESTS) private manifests: DynamicComponentManifest[],
        private loader: NgModuleFactoryLoader,
        private _injector: Injector,
        private _compiler: Compiler) {}
    
    /** Retrieve a ComponentFactory, based on the specified componentId (defined in the DynamicComponentManifest array). */
    
    getComponentFactory<T>(componentId: string, _injector?: Injector): Observable<ComponentFactory<T>> {
      const manifest = this.manifests
        .find(m => m.componentId === componentId);
      if (!manifest) {
        return ObservableThrow(`DynamicComponentLoader: Unknown componentId "${componentId}"`);
      }
    
      const p = this.loader.load(manifest.loadChildren)
        .then(ngModuleFactory => {
          const moduleRef = ngModuleFactory.create(_injector || this._injector);
          const dynamicComponentType = moduleRef.injector.get(DYNAMIC_COMPONENT);
          if (!dynamicComponentType) {
            throw new Error(
              `DynamicComponentLoader: Dynamic module for componentId "${componentId}" does not contain DYNAMIC_COMPONENT as a provider.`,
            );
          }
    
          return moduleRef.componentFactoryResolver.resolveComponentFactory<T>(dynamicComponentType);
        });
    
      return ObservableFromPromise(p);
    }

库/网格模块.ts •在gridModule中,我们尝试进行服务调用以获取组件工厂,然后可以将其馈送到AgGridModule。

export function init_app(dynamicComponentLoader?: DynamicComponentLoader) {
    return dynamicComponentLoader.getComponentFactory()
        .subscribe(components => {
            const dynamicComp = components;

        }, error => {
            console.warn(error);
        });
}

@NgModule({
    imports: [
        CommonModule,
        HttpClientModule,
        FormsModule,
        AgGridModule.withComponents(init_app), // this accepts array of components
    ],
    exports: [GridComponent],
    declarations: [GridComponent],
    entryComponents: [],
    providers: [GridApiService],
    bootstrap: [GridComponent]

})


export class parentModule {
    constructor() {}
}

问题:

我们希望我们的消费者定义他们的组件,该组件将通过清单传递给ag-grid并将其传递给我们的库,我们可以在编译时解析该库并将其传递给ag-grid。但是,由于加载模块的生命周期不同,我们感到AgGridModule.withcomponents()比我们的ParentModule.forRoot(manifests)还要执行。由于在编译时未获取组件,因此此流程未加载ag-grid。 我们如何解决此问题,以便我们的ParentModule首先加载并准备好使用消费者应用程序的组件,然后传递给AgGridModule.withcomponents()

0 个答案:

没有答案