【问题标题】:Extending component and view in angular以角度扩展组件和视图
【发布时间】:2021-09-03 23:37:38
【问题描述】:

我说在 Angular 11 上工作。问题很简单。但我没有找到任何答案。我尝试在 Angular 中使用 OOP 概念。我有一个包含 20 多个字段的基本接口。

export interface IBaseOperator{
    type:EOperatorType;
    firstname:string;
    lastname:string;
    date:string;
    nic:string;
    // Other field are removed for easiness
}

这个接口有超过 6 个子接口。我不显示所有接口,但对于 Eg

export interface IStaff extends IBaseOperator{
    empId:string;
    // some other fields
}

export interface IContractor extends IBaseOperator{
    regId:string;
    joinedDate:string;
    // some other fields
}

当我在 html 中创建用于保存的视图时,我需要创建 IBaseOperator 的所有 <input> 字段以及每个组件中的子字段。这会导致所有子项中 IBaseOperator 字段的代码重复。并且所有 6 个孩子的 save(), update(), delete() 的相同功能将被复制。但唯一不同的是,有些字段需要初始化。目前我在做

对于员工组件

this.operatorForm = this.fb.group({
      firstname: ['', Validators.required],             // IBaseOpertor
      lastname: ['', Validators.required],              // IBaseOpertor 
      date: ['', Validators.required],                  // IBaseOpertor
      nic: ['', Validators.required],                   // IBaseOpertor
      
      type:[EOperatorType.STAFF,Validators.required]    // IBaseOpertor
      empId: ['', Validators.required]                  // IStaff
    });

对于承包商组件

this.operatorForm = this.fb.group({
      firstname: ['', Validators.required],             // IBaseOpertor
      lastname: ['', Validators.required],              // IBaseOpertor 
      date: ['', Validators.required],                  // IBaseOpertor
      nic: ['', Validators.required],                   // IBaseOpertor
      
      type:[EOperatorType.CONTRACTOR,Validators.required]   // IBaseOpertor
      regId: ['', Validators.required]                  // IContractor 
      joinedDate: ['', Validators.required]             // IContractor 
    });

我在这里发现了一些问题

  1. 所有 6 个 html 文件和 ts 文件中的代码重复
  2. 如果我需要更改 IBaseOperator 接口,我需要更改所有 6 个组件。
  3. 代码重复,浪费时间和无用代码。

我的问题是,是否可以在组件(html 和 ts)中使用继承?例如 : 是否有可能在BaseComponent.html 中拥有所有子级的公共<input> 字段(IBaseOperator)和BaseComponent.ts 中的公共功能,所以当我扩展这个组件时,公共字段需要从父组件继承?我该怎么做?

提前致谢。

【问题讨论】:

  • 一种选择是创建表示接口中定义的字段的表单组件(不包括您正在扩展的接口中的字段)。然后在您的模板中,将表单组件组合在一起以创建一个完整的对象。
  • 这是一个非常普遍的问题,许多框架都试图解决它——但仍然没有完美的解决方案。不确定您期望的答案是什么
  • 合约应该如何减少代码重复?上述合约的实现应该减少代码重复。

标签: angular typescript angular11


【解决方案1】:

通用字段和方法通过'extends'关键字继承

这是一个如何扩展表单组的示例,这样您只需声明一次表单控件

export class ParentComponent {
  form:FormGroup
  date= ''

  commonfunction(){
    
  }
  constructor(protected fb: FormBuilder) {
    this.form = this.fb.group({
      date: ['', Validators.required],                  // IBaseOpertor
    })
  }
}
export class ChildComponent extends ParentComponent {
  //extends Parent component, so already has 'form' and 'date' properties
  firstname= ''
  lastname= ''
  nic= ''
  empId= ''

  constructor(protected fb: FormBuilder) {
    super(fb) //parentComponent constructor run
    this.commonfunction() //extended from parent
    this.form = this.fb.group({
      ...this.form.controls, //form already initialized because of the call to super()
      firstname: ['', Validators.required],             // IBaseOpertor
      lastname: ['', Validators.required],              // IBaseOpertor
      nic: ['', Validators.required],                   // IBaseOpertor
      empId: ['', Validators.required]                  // IStaff
    });
  }
}

在子组件中,由于上面使用了spread syntax(“...this.form.controls”),所以form属性也有'date'的控件

【讨论】:

  • 这是我尝试做的,在此之前我有一个问题。为什么 firstname、lastname 和 nic 需要在子组件中初始化,因为它们是父组件的属性?
  • 如果它们在父级中初始化,则不必在子级中初始化。抱歉,我只是从您的示例中获取了随机属性,而没有查看哪个是孩子,哪个是父母。如果你交换了属性,它仍然可以工作。
【解决方案2】:

所以基本上你需要显示一个可编辑的表单。您可以使用https://formly.dev/ui/material(或其他替代方法)作为表单,并将不同的字段(除了一组常用字段)作为输入传递给显示表单的通用组件。它是组合而不是继承 - 仍然是 OOP。

【讨论】:

    猜你喜欢
    • 2016-11-13
    • 2018-03-01
    • 1970-01-01
    • 2013-05-23
    • 2019-05-22
    • 2015-04-03
    • 2019-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多