修补FormGroup时如何让有角反应形式PatchValue()忽略空值

时间:2018-12-13 16:20:40

标签: angular angular-reactive-forms angular-forms

对于我正在构建的应用程序,我正在从API检索数据,并使用该响应直接设置表单。为此,我正在使用反应形式模块。我建立了表格,使其与我从API获取的对象匹配。问题在于某些字段应该是对象(FormGroup),但为空时为NULL。这将导致错误“无法将未定义或null转换为对象”。

FormGroup实例:

note: this.formBuilder.group({
   turnbook_file: [''],
   note: [''],
   additional_files: ['']
});

来自API的响应

  note: NULL

我的想法是,可能会放置OR语句或在您定义FormGroup的地方添加这样的内容:

note: this.formBuilder.group({
   turnbook_file: [''],
   note: [''],
   additional_files: ['']
} | NULL);

我对Angular来说还很陌生,所以我完全不了解这个问题。我在Angular Reactive Forms文档中找不到解决方案。我希望这里有人可以帮助我!

7 个答案:

答案 0 :(得分:1)

您可以尝试使用lodash pickBy方法包装api响应,然后再使用它。

import * as _ from 'lodash';
...
//fetch data from API
note.patchValue(
    _.pickBy(apiResponse)
);
...

答案 1 :(得分:0)

您可以这样定义表格

note =new FormGroup({
   'turnbook_file': new FormControl(null),
   'note: new FormControl(null),
   'additional_files': new FormControl(null)
})

答案 2 :(得分:0)

如果您定义表单和控件,则必须将值传递给它,因此,如果您的响应为空,则设置这样的表单控件的值

note.setValue({
'turnbook_file': data.turnbook_file == null ? "": data.turnbook_file,
   'note: ,data.note == null ? "": data.note,
   'additional_files': data.additional_files == null ? "": 
    data.additional_files,
})

答案 3 :(得分:0)

您可以在修补表单之前简单地过滤掉这些值

const obj = {
  foo: "bar",
  bar: null,
  cat: undefined,
  dog: "bark"
}

const truthy = Object.keys(obj).filter(item => obj[item] != undefined || obj[item] != null );
const newObj = {};
truthy.forEach(item =>Object.assign(newObj, { [item]: obj[item]}));
console.log(newObj) // { foo: "bar", dog: "bark" }

一旦您过滤掉了伪造的值,就可以用它来修补表格

答案 4 :(得分:0)

想到两个解决方案

修改FormGroup原型

@NgModule({...})
export class AppModule {

  constructor() {
    const builtInFunction = FormGroup.prototype.patchValue;
    FormGroup.prototype.patchValue = function (value, options?) {
      builtInFunction.call(this, value || {}, options);
    }
  }

}

扩展FormGroup类

import {FormGroup, ValidatorFn, AbstractControlOptions, AsyncValidatorFn} from '@angular/forms';

export class MyFormGroup extends FormGroup {

  constructor(
    controls: {[key: string]: any},
    validatorOrOpts?: ValidatorFn | ValidatorFn[] | AbstractControlOptions | null,
    asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null
  ) {
    super(controls, validatorOrOpts, asyncValidator);  
  }

  patchValue(value: {[key: string]: any}, options: {onlySelf?: boolean, emitEvent?: boolean} = {}) {
    super.patchValue(value || {}, options);
  }

}

答案 5 :(得分:0)

简短答案: 在Angular Forms API的当前实现中-无法创建/修补具有FormGroupnull值的undefined

原因:在所有new FormGroup(), formBuilder.group(), patchValue()场景中,都有一个方法Object.keys()的调用,该方法会抛出错误Cannot convert undefined or null to object(根据JS规范),如果我们将null/undefined作为参数传递。

证明

  • FormBuilder的{​​{1}}方法(source code link):

    group()
  • group(controlsConfig: {[key: string]: any}, ...) { const controls = this._reduceControls(controlsConfig); ... } _reduceControls(controlsConfig: {[k: string]: any}) { Object.keys(controlsConfig).forEach(...); ... } 的{​​{1}}(source code link):

    FormGroup

解决方法

  • 在后端更改您的API响应,以便它将发送空对象patchValue而不是null;
  • 一旦在前端收到响应,就可以进行映射:从null到{};
  • 扩展patchValue(value: {[key: string]: any}, ...) { Object.keys(value).forEach(...); ... } 类并创建一个新的类,您可以在其中重写{}:检查参数是否为FormGroup-改用空对象。
  • 扩展constructor/patchValue服务并创建您自己的Singleton服务(在您的应用程序中随处使用),您可以在其中覆盖null/undefined方法(请参见上一节)。

答案 6 :(得分:0)

改进 bestbrain10 答案。您可以同时使用 pickBy 和 isDefined。

import { isEmpty, pickBy ,isUndefined,isNull} from 'lodash';
// Fetch data and remove all falsy  keys

this.formgroup.patchValue(
_.omitBy(formData, (v) => _.isUndefined(v) || _.isNull(v) || v === ''));