覆盖导入模块的组件声明

j2L*_*L4e 7 angular

你可以覆盖第三方模块的组件声明吗?

假设您正在使用声明并导出两个组件的第三方模块:

@NgModule({
  exports: [Cmp1, Cmp2]
  declarations: [Cmp1, Cmp2]
})
export class ThirdPartyModule {}
Run Code Online (Sandbox Code Playgroud)

Cmp1的模板:

`<app-cmp2></app-cmp2>`
Run Code Online (Sandbox Code Playgroud)

Cmp2的模板:

`<p>foo</p>`
Run Code Online (Sandbox Code Playgroud)

AppModule进口ThirdPartyModule:

@NgModule({
  ...
  imports: [ThirdPartyModule],
  declarations: [AppComponent]
})
export class AppModule {}
Run Code Online (Sandbox Code Playgroud)

AppComponent的模板就是<app-cmp1></app-cmp1>.

你将如何重新声明/覆盖的第三方模块的实现Cmp2,这样不Cmp2MyCmp2在内部呈现Cmp1

显然我需要扩展Cmp2(或实现其接口):

@Component({
  ... // same selector as Cmp2
})
export const MyCmp2 extends Cmp2 {}
Run Code Online (Sandbox Code Playgroud)

我尝试通过DI提供它:{ provide: Cmp2, useClass: MyCmp2 }这不起作用.

简单地在app模块中声明它也不会起作用,因为当两个组件匹配相同的选择器时,角度会抛出.这甚至可能吗?

我的具体用例是覆盖材质水平步进器的标题组件.

gol*_*das 1

不可能按照您描述的方式执行此操作,因为您要么声明两个具有相同名称的组件,要么根本不声明任何组件。

一种可能的解决方案是将ComponentFactoryResolver与配置服务结合使用。

假设您想在两个不同的模块和上使用ComposableComponent不同的InnerComponent(或InnerComponent1)。InnerComponent2ComposedWithInner1ModuleComposedWithInner2Module

ComposedWithInner1Module定义为:

@NgModule({
  imports: [ComposableComponentModule],
  providers: [
    {
      provide: Config,
      useValue: { component: InnerComponent1 }
    }
  ],
})
export class ComposedWithInner1Module {}
Run Code Online (Sandbox Code Playgroud)

ComposedWithInner2Module定义为:

@NgModule({
  imports: [ComposableComponentModule],
  providers: [
    {
      provide: Config,
      useValue: { component: InnerComponent2 }
    }
  ],
})
export class ComposedWithInner2Module {}
Run Code Online (Sandbox Code Playgroud)

您需要ComposableComponentModule说明两者InnerComponent2InnerComponent1可以动态注入,这是通过entryComponents属性完成的:

@NgModule({
  declarations: [ComposableComponent],
  exports: [ComposableComponent]
  entryComponents: [InnerComponent2, InnerComponent1]

})
export class ComposableComponentModule {}
Run Code Online (Sandbox Code Playgroud)

然后通过注入ComposableComponent获取注入并将其加载到模板中:InnerComponentXConfigComponentFactoryResolver

@Component({
  selector: 'prl-column-header-extras',
  template: '<p> I'll be substituted by InnerComponent2 or InnerComponent1 </p>'
})
export class ComposableComponent implements OnInit {
  constructor(
    private config: Config,
    private componentFactoryResolver: ComponentFactoryResolver
  ) {}

  ngOnInit() {
    const comp = this.componentFactoryResolver.resolveComponentFactory(
      this.config.component
    );

    this.viewContainerRef.clear();
    const ref = this.viewContainerRef.createComponent(comp);

    ref.changeDetectorRef.markForCheck();
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这种方法要求“ComposableComponent”的设计具有可组合性。它不允许您将子组件注入任意父组件。 (2认同)