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
) 引入扩展标准表单类(如 AbstractControl
、FormControl
等)的通用接口。它不引入任何新功能,并且在编译后的 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<UserFormValue>
【讨论】:
【参考方案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 强类型反应形式的主要内容,如果未能解决你的问题,请参考以下文章