【问题标题】:Override imported module's component declaration覆盖导入模块的组件声明
【发布时间】:2018-12-11 04:25:36
【问题描述】:

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

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

@NgModule({
  exports: [Cmp1, Cmp2]
  declarations: [Cmp1, Cmp2]
})
export class ThirdPartyModule {}

Cmp1的模板:

`<app-cmp2></app-cmp2>`

Cmp2的模板:

`<p>foo</p>`

AppModule 导入ThirdPartyModule

@NgModule({
  ...
  imports: [ThirdPartyModule],
  declarations: [AppComponent]
})
export class AppModule {}

AppComponent 的模板就是&lt;app-cmp1&gt;&lt;/app-cmp1&gt;

您将如何重新声明/覆盖第三方模块对Cmp2 的实现,以便在Cmp1 中呈现的不是Cmp2,而是MyCmp2

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

@Component({
  ... // same selector as Cmp2
})
export const MyCmp2 extends Cmp2 {}

我尝试通过 DI:{ provide: Cmp2, useClass: MyCmp2 } 提供它,但没有成功。

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

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

【问题讨论】:

  • 嗨,如果您找到了答案或解决方法,我目前与您遇到的问题相同。请你能指出我正确的方向吗?这是我的问题stackoverflow.com/questions/57955904/…
  • 对不起,我没有
  • 好的,谢谢,这很难
  • 嗨@j2L4e,我面临着完全相同的情况。只是想检查一下自从 ErnestoAlfonso 发表评论后您是否找到任何解决方案
  • 我们没有进一步尝试,抱歉。

标签: angular


【解决方案1】:

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

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

假设您想在两个不同的模块ComposedWithInner1ModuleComposedWithInner2Module 上使用ComposableComponent 和不同的InnerComponentInnerComponent1InnerComponent2)。

ComposedWithInner1Module 定义为:

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

ComposedWithInner2Module 定义为:

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

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

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

})
export class ComposableComponentModule {}

然后ComposableComponent通过注入的Config获取注入的InnerComponentX并用ComponentFactoryResolver加载到模板中:

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

【讨论】:

  • 这种方法需要 ComposableComponent 设计为可组合性。它不允许您将子组件注入任意父组件。
  • 是的,你是对的。我认为不可能通过 ngModule 来“躲避类型”组件。 Angular 喜欢它的样板。
猜你喜欢
  • 2021-11-04
  • 1970-01-01
  • 2011-10-05
  • 2018-06-25
  • 1970-01-01
  • 1970-01-01
  • 2018-10-20
  • 2021-02-26
  • 2020-08-27
相关资源
最近更新 更多