Angular 强类型反应形式

Posted

技术标签:

【中文标题】Angular 强类型反应形式【英文标题】:Angular strongly typed reactive forms 【发布时间】:2019-07-29 21:51:24 【问题描述】:

我希望在我的 Angular 项目中重构大量组件,使其具有强类型的 FormGroups、FormArrays 和 FormControls。

我只是在寻找一种实现强类型响应式表单的好方法。任何人都可以根据自己的经验提供建议/建议吗?

谢谢。

编辑:

为了澄清,强类型是指目前当我创建 FormGroup 或 FormArray 时,我无法指定其中实际表单的结构。当我将此表单传递给我的应用程序中的各种组件时,我会觉得我让维护变得更加困难。

【问题讨论】:

你的strongly-typed的意思在这里不是很清楚。您能否举个例子来详细说明您在寻找什么? @SiddAmjera 澄清一下,强类型是指目前当我创建 FormGroup 或 FormArray 时,我无法指定其中实际表单的结构。当我将此表单传递给我的应用程序中的各个组件时,我会觉得我让维护变得更加困难。 您是否可以创建一个示例 StackBlitz,尽可能少地复制您的场景? @SiddAmjera 对不起,也许我解释得不够清楚。这不是一段特定的代码。但希望这可以解释问题:stackblitz.com/edit/angular-tlfrgt Angular 团队目前正在研究它,他们拥有通用/类型化形式的 MVP! github.com/angular/angular/issues/13721#issuecomment-942910823 【参考方案1】:

最优雅的解决方案是利用 TypeScript 声明文件 (*.d.ts) 引入扩展标准表单类(如 AbstractControlFormControl 等)的通用接口。它不引入任何新功能,并且在编译后的 javascript,但同时强制执行强类型检查。

今年 3 月 Daniele Morosinotto 的 suggested 和 there are talks 现在将其包含在 Angular 9 中。

采用该解决方案很简单:

    从this gist 下载TypedForms.d.ts 并将其另存为src/typings.d.ts 在您的项目中(Angular 6+ 已经知道如何使用此文件)。 只要您需要强类型验证(参见that gist 或stackblitz 中的示例),就开始使用新类型(FormGroupTyped<T>FormControlTyped<T> 等)。

有关更多信息,请查看blog post 分析强类型表单的可用解决方案。

【讨论】:

从哪里导入FormGroupTyped 没关系,我使用的是 Lib,您还必须将 TypedForms.d.ts 文件复制到每个库中......【参考方案2】:

我最终使用的解决方案是library I found called ngx-strongly-typed-forms

它使您能够拥有强类型的 FormControls、FormGroups 和 FormArrays。有一些限制,但它肯定对我的项目有很大帮助。

您可以在https://github.com/no0x9d/ngx-strongly-typed-forms查看文档

【讨论】:

我在一个多月前创建了一个问题,但似乎还没有得到任何回应。从外观上看,这个项目可能已经过时了,我不建议任何人使用它! 缺少类型信息的(仍未解决的)角度问题是github.com/angular/angular/issues/13721。那里提到了一些更强大的替代方案(如@ng-stack/forms)。【参考方案3】:

我遇到了类似的问题,这是我的解决方案。我真的只关心表单的“价值”类型,而不是表单本身。它最终看起来像这样。

export interface UserFormValue 
  first_name: string
  last_name: string
  referral: string
  email: string
  password: string

...

ngOnInit() 
  this.userForm = this.fb.group(
    first_name: [ '', Validators.required ],
    last_name: [ '', Validators.required ],
    referral: [ '' ],
    email: [ '', [ Validators.required, Validators.email ] ],
    password: [ '', [ Validators.required, Validators.minLength(8) ] ],
  );


...

然后在模板中提交值

<form [formGroup]="userForm" (ngSubmit)="onSubmit(userForm.value)">
   ...
</form>

现在您可以向提交函数添加类型

onSubmit(userForm: UserFormValue) 
   ...

它并不完美,但对于我的用例来说已经足够了。我真希望有这样的。

userForm: FormGroup&lt;UserFormValue&gt;

【讨论】:

【参考方案4】:

对于那些想要另一种解决方案的人。我发现this article 谈论有角形式的强类型。以下是我的总结。

interface Person 
  name: string;
  email: string


// Controls in a form group that would emit a Person as it's value
type PersonControls =  [key in keyof Person]: AbstractControl ;
type PersonFormGroup = FormGroup &  value: Person, controls: PersonControls ;

export class MyFormComponent 
  form = new FormGroup(
    name: new FormControl(),
    email: new FormControl()
   as PersonControls) as PersonFormGroup;

  init() 
    const name = this.form.controls.name; // strong typed!
  

【讨论】:

我更喜欢这个。谢谢!【参考方案5】:

如果您有嵌套类型的组,那么您可以这样做: **models.ts

export type TCreateUserFields = 
    first_name: string,
    last_name: string,
    accept_terms: boolean,
;
export type TPasswordsControls = 
    passwords: FormGroup & 
        password: AbstractControl,
        confirm_password: AbstractControl
    

export type TPasswordsFields = 
    passwords: 
        password: string,
        confirm_password: string
    

export type TAllFields = TCreateUserFields & TPasswordsFields;
export type TAllControls = TCreateUserControls & TPasswordsControls;
export type TCreateUserControls = 
    [key in keyof TCreateUserFields]: AbstractControl
;
export type TCreateUserFormGroup = FormGroup & value: TAllFields, controls: TAllControls;
**组件.ts
this.registerationForm = this.fb.group(

    first_name: new FormControl("", [Validators.required]),
    last_name: new FormControl("", [Validators.required]),
    accept_terms: new FormControl(false, [Validators.required]),
    passwords: new FormGroup(
        
            password: new FormControl("", [Validators.required, Validators.pattern(/^[~`!@#$%^&*()_+=[\]\|;':",.\/<>?a-zA-Z0-9-]+$/)]),
            confirm_password: new FormControl("", [Validators.required, Validators.pattern(/^[~`!@#$%^&*()_+=[\]\|;':",.\/<>?a-zA-Z0-9-]+$/)]),
        ,  
            validators: <ValidatorFn>pwdConfirming(key:'password', confirmationKey:'confirm_password')
        
    )
 as TCreateUserControls) as TCreateUserFormGroup;

【讨论】:

以上是关于Angular 强类型反应形式的主要内容,如果未能解决你的问题,请参考以下文章

强类型对象中的 TypeScript 循环约束

弱类型和强类型的优缺点

java中list强转为map类型

关于java内存泄露的总结--引用的类型:强引用,弱引用,软引用

Python 是强类型的吗?

强/若类型语言 动/静态语言