【问题标题】:Make changes in template when overriding a component in Angular在 Angular 中覆盖组件时在模板中进行更改
【发布时间】:2019-12-30 18:46:46
【问题描述】:

问题(Angular 7)

我希望能够在不重写整个模板的情况下“修改”被覆盖组件的模板,这意味着它将与它所覆盖的组件共享相同的 html 模板。目标是能够自定义组件,并且覆盖组件模板上的任何更改都将直接反映在覆盖组件中。

也许我们可以说我想在两个组件之间共享部分逻辑和模板。

当前实现示例

@Component({
  selector: 'component-a',
  templateUrl: './component-a.html'
})
export class ComponentAComponent {

  constructor() { }
}
@Component({
  selector: 'component-a',
  templateUrl: './component-a2.html'
})
export class ComponentA2Component extends ComponentAComponent {

 specificStuff = 'I am additional stuff';

  constructor() { }
}

component-a2.component.html

...
[ same as beginning of component-a.component.html]
...
<!-- Some specific stuff like an additional label, button, mat form field -->
<div>
  {{ specificStuff }}
</div>
...
[ same as end of component-a.component.html]
...

如我们所见,如果我更改component-a.html,它不会影响componentA2。

目标

目标是两个组件使用相同的模板,但最终(编译)DOM 会有所不同。我不想用 ngIf 做这个。

类似

@Component({
  selector: 'component-a',
  templateUrl: './component-a.html'
})
export class ComponentAComponent {

  public specificStuff;

  constructor() { }
}
@Component({
  selector: 'component-a',
  templateUrl: './component-a.html'
})
export class ComponentA2Component extends ComponentAComponent {

 public name = 'World';
 public specificStuff = '<div> Hello {{name}} </div>';

  constructor() { }
}

组件-a.component.html

<div>Yo</div>
<ng-template #specificStuff></ng-template>
<div>Bye</div>

组件A的结果模板:

<div>Yo</div>
<ng-template #specificStuff></ng-template>
<div>Bye</div>

componentA2 的结果模板:

<div>Yo</div>
<ng-template #specificStuff><div> Hello {{name}} </div></ng-template>
<div>Bye</div>

我看到了什么

innerHTML: 不适用于角度插值、指令等。

ngComponentOutlet: 需要创建另一个组件并处理上下文 + 我想避免在组件选择器中包含一个层以避免破坏样式

ngTemplateOutlet: 模板仍然需要以某种方式传递吗? (也许这是我需要但不知道如何使用它)

【问题讨论】:

  • 也许你想使用内容投影。 angular.io/guide/lifecycle-hooks#content-projection
  • 如果我没记错的话,我仍然需要更改注入我的组件的组件的模板才能设置内容,所以我也需要“覆盖”这个组件。这不是我真正想要的。我希望能够从组件本身“自定义”组件。
  • 如果不完全重写模板,您将无法做到这一点。想想 Angular 在运行时对你的模板有什么了解(如果你做 AOT)。
  • 不可能是一个可以接受的答案。我想我在研究之后真正需要的是某种东西,比如 pug、nunjucks、带有模板继承的 EJS。非常感谢您的建议。

标签: angular overriding angular2-template


【解决方案1】:

如果我了解您希望在组件之间共享逻辑和状态。 为此,您可以创建一个包含此属性的类。

例如:

export class FeatureCore {
    public stuff = 'stuff';
    public specificStuff = '<div> Hello {{name}} </div>';
}

...

export class ComponentA2Component extends FeatureCore implements OnInit {
    constructor() {
        super()
    }
    ngOnInit(): void {
    console.log(this.stuff); // 'stuff'
    }
}

这个 extends 方法应该在你的其他组件中实现。 考虑使用 RxJS 运算符来获取值流。

【讨论】:

  • 不,我不是这个意思。更多的是关于模板共享。
【解决方案2】:

您可能想使用角度内容投影:

https://angular.io/guide/lifecycle-hooks#content-projection

https://stackblitz.com/edit/angular-projection-content-ab?file=src/app/app.component.ts

否则,您可以将模板作为参数传递给组件 a。请记住,您可以有多个内容投影槽。

import { Component, Input } from '@angular/core';

@Component({
  selector: 'component-a',
  template: `

    <p> component A begining <p>
    <ng-content></ng-content>
    <p> component A ending <p>

    `,
})
export class ComponentA  {

}
import { Component, Input } from '@angular/core';

@Component({
  selector: 'component-b',
  template: `
  <component-a>
  <h1>This is from component B</h1>
  </component-a>
  `,
})
export class ComponentB  {
   // you can inherit componentA if it makes things easier. I would keep them separate
}

【讨论】:

  • 这仍然会导致最终的 DOM 会有 层的问题。
  • @Tino 我不认为你想要的现在用 angular 是可能的。
【解决方案3】:

据我了解,您需要添加一些条件来解决您的问题。 您可以在同一个组件中同时拥有这两种情况。

或者是否有理由需要两个独立的组件?

您可以做类似的事情并继续使用模板来显示特定内容。

<div>Yo</div>
<div *ngIf="yourVariable; else specificStuff">
    Hello, there is no specific stuff here.
</div>
<div>Bye</div>

<ng-template #specificStuff><div> Hello {{name}} </div></ng-template>

【讨论】:

  • 我想避免这种情况的原因是同一个组件可能会被多次覆盖(没有确定的数字),因此我希望尽可能地保持模板和逻辑的具体化。所以这个组件将以更好的方式扩展。
  • @Tino 我完全错过了你提到你不想在帖子中使用 ngIf。因此,如果这不是一个选择,我认为安德烈的答案应该适合你。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-13
  • 2020-11-16
  • 2022-01-12
  • 2018-02-13
  • 2012-06-14
  • 2014-01-28
  • 1970-01-01
相关资源
最近更新 更多