手动设置FormBuilder控件的值


175

这真让我发疯,我不知所措,不能再为此花整整一天的时间。

我正在尝试在组件内手动设置一个控制值('dept'),但它不起作用-甚至新值也无法正常记录。

这是FormBuilder实例:

initForm() {
  this.form = this.fb.group({
    'name': ['', Validators.required],
    'dept': ['', Validators.required],
    'description': ['', Validators.required],
  });
}

这是接收选定的部门的事件处理程序:

deptSelected(selected: { id: string; text: string }) {
  console.log(selected) // Shows proper selection!

  // This is how I am trying to set the value
  this.form.controls['dept'].value = selected.id;
}

现在,提交表单并注销后,this.form该字段仍为空白!我看过其他ppl的用法,updateValue()但这是beta.1,但我不认为这是调用控件的有效方法。

我也曾尝试致电updateValueAndValidity()失败,:(。

我只会ngControl="dept"在form元素上使用,就像我在处理表单的其余部分一样,但是它是一个自定义指令/组件。

<ng-select
  [data]="dept"
  [multiple]="false"
  [items]="depts"
  (selected)="deptSelected($event)" <!-- This is how the value gets to me -->
  [placeholder]="'No Dept Selected'"></ng-select>

我遇到过类似的情况,这种情况是在http.get-subscribe中设置了值并加载了表单值,但是设置了先执行的值行,之后才真正将订阅作为异步执行。因此在订阅中设置值确保其设置。my2cents!
HydTechie

Answers:


325

更新日期:19/03/2017

this.form.controls['dept'].setValue(selected.id);

旧:

现在,我们被迫进行类型转换:

(<Control>this.form.controls['dept']).updateValue(selected.id)

我不太优雅。希望在将来的版本中对此进行改进。


6
很好,谢谢。还需要清除验证信息: (<Control>this.form.controls['dept']).setErrors(null)
叫Haney的男子

17
还是this.form.get('dept').setValue(selected.id):)
developer033

6
请注意。您也可以不使用索引器直接访问属性。this.form.controls.dept.setValue(selected.id);
James Poulose

但这不会对新数据执行验证!更新后如何手动触发变更检测?
ksh

1
对我来说这是2019年的作品:this.form.controls['dept'].setValue(selected.id);
约翰·洛佩兹

98

在Angular 2 Final(RC5 +)中,有新的API用于更新表单值。该patchValue()API方法支持部分格式的更新,在这里我们只需要指定某些字段:

this.form.patchValue({id: selected.id})

还有一种setValue()API方法需要具有所有表单字段的对象。如果缺少字段,我们将收到错误消息。


7
只是要补充一点,即现在updateValue(从Filoche接受的答案中)赞成使用setValue
-superjos

2
这是对Github 的正式拉取请求,以及弃用updateValue()和引入patchValueand 的理由setValue
TheBrockEllis '16

但这不会对新数据执行验证!更新后如何手动触发变更检测
ksh19,19年

16

Aangular 2 final已更新了API。他们为此添加了许多方法。

要从控制器更新表单控件,请执行以下操作:

this.form.controls['dept'].setValue(selected.id);

this.form.controls['dept'].patchValue(selected.id);

无需重置错误

参考资料

https://angular.io/docs/ts/latest/api/forms/index/FormControl-class.html

https://toddmotto.com/angular-2-form-controls-patch-value-set-value


两者之间的差异- setValue()在上调用时formGroup/formBuilder,需要设置表格下的所有值。patchValue(),当在同一位置调用时,可用于更新特定值。
Vibhor Dube

11

您可以使用以下方法来更新反应形式控件的值。以下任何一种方法都可以满足您的需要。

使用setValue()的方法

this.form.get("dept").setValue(selected.id);
this.form.controls["dept"].setValue(selected.id);

使用patchValue()的方法

this.form.get("dept").patchValue(selected.id);
this.form.controls['dept'].patchValue(selected.id);
this.form.patchValue({"dept": selected.id});

last方法将循环遍历表单中的所有控件,因此在更新单个控件时不建议使用

您可以在事件处理程序中使用任何方法

deptSelected(selected: { id: string; text: string }) {
     // any of the above method can be added here
}

您可以根据需要使用以下方式更新表单组中的多个控件:

this.form.patchValue({"dept": selected.id, "description":"description value"});

9

您可以尝试以下方法:

deptSelected(selected: { id: string; text: string }) {
  console.log(selected) // Shows proper selection!

  // This is how I am trying to set the value
  this.form.controls['dept'].updateValue(selected.id);
}

有关更多详细信息,您可以查看有关updateValue方法第二个参数的相应JS文档:https//github.com/angular/angular/blob/master/modules/angular2/src/common/forms/model。 ts#L269


感谢您的答复-但是updateValue在angular2 beta.1中似乎不是有效的方法。1-您在哪个版本上可以使用该方法?
马修·布朗

1
Typescript出现以下错误:error TS2339: Property 'updateValue' does not exist on type 'AbstractControl'。在该组件中,表单的类型为ControlGroup。也许如果我用它们单独创建它们new Control()会起作用
Matthew Brown

5

这些都不对我有用。我必须做:

  this.myForm.get('myVal').setValue(val);

我也一样 为什么会这样呢?
Rehmanali Momin

3
  let cloneObj = Object.assign({}, this.form.getRawValue(), someClass);
  this.form.complexForm.patchValue(cloneObj);

如果您不想手动设置每个字段。


2

@Filoche的Angular 2更新了解决方案。使用FormControl

(<Control>this.form.controls['dept']).updateValue(selected.id)

import { FormControl } from '@angular/forms';

(<FormControl>this.form.controls['dept']).setValue(selected.id));

或者,您可以使用@AngularUniversity的解决方案,该解决方案使用patchValue


1

我知道答案已经给出,但是我想简短地回答一下如何更新表单的值,以便其他新手可以清楚地了解。

您的表单结构非常适合以其为例。因此,在我的回答中,我将其表示为表格。

this.form = this.fb.group({
    'name': ['', Validators.required],
    'dept': ['', Validators.required],
    'description': ['', Validators.required]
  });

因此我们的表单是具有三个FormControl的对象的FormGroup类型。

有两种方法可以更新模型值:

  • 使用setValue()方法可以为单个控件设置新值。setValue()方法严格遵守表单组的结构,并替换控件的整个值。

  • 使用patchValue()方法替换在对象对象中定义的,在表单模型中已更改的属性。

对setValue()方法的严格检查有助于捕获复杂形式的嵌套错误,而patchValue()在这些错误上会静默失败。

从角官方文档 在这里

因此,在更新包含多个控件的表单组实例的值时,但是您可能只想更新模型的某些部分。patchValue()是您要寻找的。

让我们来看一个例子。当您使用patchValue()

this.form.patchValue({
    dept: 1 
});
//here we are just updating only dept field and it will work.

但是当您使用setValue()时,您需要更新完整模型,因为它严格遵守表单组的结构。所以,如果我们写

this.form.setValue({
    dept: 1 
});
// it will throw error.

我们必须传递表单组模型的所有属性。像这样

this.form.setValue({
      name: 'Mr. Bean'
      dept: 1,
      description: 'spome description'
  });

但我不经常使用这种样式。我更喜欢使用以下方法来帮助使我的代码更简洁,更易理解。

我要做的是,将所有控件声明为单独的变量,然后使用setValue()更新该特定控件。

对于上面的表格,我会做这样的事情。

get companyIdentifier(): FormControl {
    return this.form.get('name') as FormControl;
}

get dept(): FormControl {
    return this.form.get('dept') as FormControl;
}

get description(): FormControl {
    return this.form.get('description') as FormControl;
}

当您需要更新表单控件时,只需使用该属性即可对其进行更新。在该示例中,当用户从下拉列表中选择一项时,发问者尝试更新部门表单控件。

deptSelected(selected: { id: string; text: string }) {
  console.log(selected) // Shows proper selection!

  // instead of using this.form.controls['dept'].setValue(selected.id), I prefer the following.

  this.dept.setValue(selected.id); // this.dept is the property that returns the 'dept' FormControl of the form.
}

我建议看看FormGroup API,以了解FormGroup的所有属性和方法。

其他:了解吸气剂请参见此处



-1

提示:如果您正在使用setValue但未在表单上提供所有属性,则会收到错误消息:

Must supply a value for form control with name: 'stateOrProvince'.

因此,您可能会想使用patchValue,但是如果您要更新整个表单,则可能很危险。我有一个address可能没有的,stateOrProvince或者stateCd取决于它是美国还是全世界。

相反,您可以像这样进行更新-它将使用null作为默认值:

this.form.setValue( { stateOrProvince: null, stateCd: null, ...address } );
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.