Angular Reactive Forms 重置值

Posted

技术标签:

【中文标题】Angular Reactive Forms 重置值【英文标题】:Angular Reactive Forms reset value 【发布时间】:2019-06-22 08:26:05 【问题描述】:

我有一个复杂的 FormGroup,其中包含多个 FormControls、FormGroups 和 FormArrys。

我需要将表单重置为其初始值。但是,可以从服务器检索初始值。这意味着我得到某种 JSON,然后将其解析到我的 FormGroup 中,我需要保存此状态才能将所有内容重置为之前的状态。

FormGroup.reset() 或 FormGroupDirective.resetForm() 只是重置控件的值,而不改变 FormArrays 的长度。

我有以下 FormGroup 结构

formGroup: FormGroup = this.fb.group(
    unitNames: this.fb.array([this.createName()], Validators.required),
    types: this.fb.array([], Validators.required),
    addresses: this.fb.array([]),
    requisites: this.fb.array([]),
    note: [null],
    mediaContent: this.fb.array([])
);

每个 FormArray 在 JSON 提取后填充有复杂的 FormGroups。

保存初始状态然后在表单重置时恢复它的最佳方法是什么?


现在我正在尝试这样做

resetForm() 
    this.formGroupDirective.resetForm();
    this.formGroup = this.fb.group(
        unitNames: this.fb.array([this.createName()], Validators.required),
        types: this.fb.array([], Validators.required),
        addresses: this.fb.array([]),
        requisites: this.fb.array([]),
        note: [null],
        mediaContent: this.fb.array([])
    );

    this.patchDeep(this.savedUnit);
    this.resetPopup.close();


patchDeep(unit) 
    if (unit.unitNames && unit.unitNames.length > 0) 
        unit.unitNames.forEach((unitName, i) => 
            this.names.setControl(i, this.createName(unitName));
        );
    

    if (unit.unitAddresses && unit.unitAddresses.length > 0) 
        unit.unitAddresses.forEach((addressGroup, i) => 
            this.addresses.setControl(i, this.fs.createAddress(addressGroup));
        );
    

但是,这种方法需要手动将 FormArray 重置为 0,这样就不会出现额外的值并且看起来不正确。


近似 JSON


    unitNames: [
        
            id: 1,
            nameTypeId: 3,
            value: 'Unit 1'
        ,
        
            id: 2,
            nameTypeId: 1,
            value: 'Unit Alias'
        
    ],
    types: [
        
            unitTypeId: 3,
            unitCode: 3131,
            unitNote: 'sample text'
        
    ],
    requisites: [
        
            country: 'UK',
            city: 'London',
            build: 'B122/1',
            phones: [
                
                    phoneType: 32,
                    value: '992-123-1'
                ,
                
                    phoneType: 1,
                    value: '123'
                
            ]
        
    ],
    note: 'Hello world'

【问题讨论】:

resetForm之后重用“从服务器检索值”时使用的逻辑 我现在可以了,但我觉得还有另一种更好的方法。因为我必须从头开始创建我的 formGroup 以不手动遍历所有 FormArrays 导致需要重新创建引用的原因(我将对表单对象的引用存储在其他地方以便于访问。此引用在 formGroup 重新创建期间丢失) 你能提供你的json对象吗? @AmiVyas 添加。这是一个近似结构,但它具有真实结构的所有属性。等于 FormControl 的简单键值对。 FormGroup 中的 FormArray。 【参考方案1】:

我现在遇到了确切的问题。既然你差不多 3 年前问过这个问题,我真的很好奇你最终得到了什么解决方案。

对我来说,似乎有两种解决方案(都同样糟糕):

    重新创建(重新绑定)根 formGroup - 这会导致您失去对原始 formGroup 的引用,但它也会破坏对 valueChanges 的所有订阅,在我的情况下,我还遇到了更改检测的问题,而不是运行和其他事情(例如,即使在我禁用了 root formGroup 之后,也启用了一些选择或复选框)。

    遍历每个 formArray 并使用 someFormArray.removeAt() 或使用 someFormArray.clear() 手动清理它 然后使用someFormArray.push() 再次添加元素。 - 这看起来是最常用的想法。当您的表单较小且不会增长时,这可能是可以接受的,您可以直接访问 someFormArray。但是当你有很大的复杂表单时,你可以尝试编写一些可能使用递归来查找 formArrays 的方法,但是编写适用于嵌套 formGroups 和 formArrays 的所有情况的通用方法可能会很痛苦。


2016 年,有人要求 form.reset() 也清理 formArray 长度,但 Angular 团队的某个人关闭了该问题,建议重新创建(重新绑定)根 formGroup。看: https://github.com/angular/angular/issues/10960

以下是堆栈上的类似问题,但答案总结了我提出的两个解决方案:

How do I clear the FormArray in Angular Reactive Forms

restore the modal original state in FormArray on "Cancel Change" button clicked in angular5

How to clear the FormArray values in angular reactive form?

FormArray length does not reset by form.reset()

How to reset formarray to one item in angular

FormArray in Angular Reactive Form not resetting on form submit

【讨论】:

我最终得到了最简单的解决方案。创建新的表单组,就是这样

以上是关于Angular Reactive Forms 重置值的主要内容,如果未能解决你的问题,请参考以下文章

Angular Reactive forms : change vs valueChanges

Angular Reactive Forms,patchValue 不起作用,嵌套表单

Angular Reactive Forms vs ngModel,哪个性能更好? [关闭]

如何为Angular Reactive Forms创建自定义验证器

Angular 2 Reactive Forms 问题如何以角度方式而不是 jquery 方式进行

如何使用 Reactive Forms (Angular2 RC3) 进行异步验证?