【问题标题】:Angular 2 Reactive Form nested group passed null on reset throw errorAngular 2 Reactive Form嵌套组在重置抛出错误时传递了null
【发布时间】:2018-04-27 03:30:33
【问题描述】:

我有这个表单组:

Id: [null],
Nominativo: [null, [Validators.required, Validators.maxLength(100)]],
Area: fb.group({
    Id: [null]
})

当我尝试使用此模型重置表单时:

Id: 1,
Nominativo: 'Test'
Area: null

区域空值抛出异常“TypeError:无法读取null的属性'Id'”。我的预期结果是所有区域值都变为空。我可以避免这个问题吗?当所有嵌套模型都为空时,我的服务器响应都为空

【问题讨论】:

  • 如何用模型重置表单?
  • 我使用 form.reset(model)。我尝试了 form.patch(model) 或 form.setValue(model) 但它们也返回错误
  • 有一个未解决的问题github.com/angular/angular/issues/20509

标签: forms angular angular2-forms angular-reactive-forms formgroups


【解决方案1】:

我建议这样做:

area.model.ts

export class Area {
 id: string;
}

data.model.ts

export class DataModel {
 id: string;
 nominativo: string;
 area: Area;
}

form.model.ts

export class FormModel {
 id: string;
 nominativo: string;
 area?: Area;
}

data-model.service.ts

@Injectable()
export class DataModelService {
  toFormModel(dataModel: DataModel): FormModel {
    const form: FormModel = new FormModel();
    form.id = dataModel.id;
    form.nominativo = dataModel.nominativo;
    if (dataModel.area) {
      form.area = dataModel.area;
    }
    return form;
 }
}

form.component.ts

constructor(dataModelService: DataModelService,
            dataApi: dataApiService,
            fb: FormBuilder) {
  this.form = this.fb.group({
    id: '',
    nominativo: '',
    area: this.fb.group({
      id: ''
    })
  });

  this.dataApi.getData()
    .map((data: DataModel) => this.dataModelService.toFormModel(data))
    .subscribe((formData) => {
       this.form.patchValue(formData);
    });
}

【讨论】:

  • 如果我用实例化模型替换嵌套模型一切正常(因为他可以访问 Area.Id)但问题是 webapi 返回空嵌套模型的空值,所以我需要一个解决方案无需更改它们
  • 我认为最好的解决方案是编写转换器,它将您的数据模型(从 api 返回)转换为表单模型。看一看:angular.io/guide/…,angular.io/guide/reactive-forms#save
  • 首先您应该创建表单定义(ngOnInit),然后在您从 api 接收数据模型后将其转换为表单模型定义并调用 form.setValue(也在表单定义后的 ngOnInit 中)
  • 问题是这是一个有效的模型(区域可以为空)。当对象为空时,我需要一些东西来告诉重置函数不要在嵌套的 formGroup 上调用 reset/setValue。
【解决方案2】:

我不认为有一个简单的干净的解决方案。您需要迭代对象属性并手动设置值。所以是这样的:

resetVal = {Id:1, Nominativo: 'Test', Area: null }

当您收到数据时,您首先检查Area 是否为空,如果是,请将表单控件设置为该表单组中的null。如果没有,则将从后端获得的值设置为表单组:

this.areaCtrl = this.myForm.controls.Area as FormGroup;

this.myForm.patchValue({
  Id: this.resetVal.Id,
  Nominativo: this.resetVal.Nominativo,
}) 
if(this.resetVal.Area === null) {
  this.areaCtrl.patchValue({
    Id: null
  })
}
else {
  for(let a in this.resetVal.Area) {
    this.areaCtrl.patchValue({         
      [a]:this.resetVal.Area[a]
    })
  }
}

DEMO

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-17
    • 2019-04-07
    • 2020-07-28
    • 2018-07-15
    • 2023-01-05
    • 2021-05-10
    • 2019-01-17
    • 1970-01-01
    相关资源
    最近更新 更多