如何在 Angular 的反应式表单中设置表单控件的值

Posted

技术标签:

【中文标题】如何在 Angular 的反应式表单中设置表单控件的值【英文标题】:How to set value to form control in Reactive Forms in Angular 【发布时间】:2019-08-11 23:43:55 【问题描述】:

大家好,我是 Angular 的新手。实际上,我正在尝试从服务订阅数据,并且该数据正在传递给我的表单控件(例如,它就像一个编辑表单)。

import  Component, OnInit  from '@angular/core';
import  FormBuilder, FormGroup, Validators, FormArray, FormControl  from '@angular/forms';
import  ActivatedRoute, Router  from '@angular/router';
import  QuestionService  from '../shared/question.service';

@Component(
  selector: 'app-update-que',
  templateUrl: './update-que.component.html',
  styleUrls: ['./update-que.component.scss']
)
export class UpdateQueComponent implements OnInit 

  questionsTypes = ['Text Type', 'Multiple choice', 'Single Select'];
  selectedQuestionType: string = "";
  question: any = ;

  constructor(private route: ActivatedRoute, private router: Router,
    private qService: QuestionService, private fb: FormBuilder)  

  

  ngOnInit() 
      this.getQuebyid();
  

  getQuebyid()
    this.route.params.subscribe(params => 
      this.qService.editQue([params['id']]).subscribe(res =>
        this.question = res;
      );
    );
  

  editqueForm =  this.fb.group(
    user: [''],
    questioning: ['', Validators.required],
    questionType: ['', Validators.required],
    options: new FormArray([])
  )

  setValue()
    this.editqueForm.setValue(user: this.question.user, questioning: this.question.questioning)
  


如果我在表单字段中使用[(ngModule)] 将值设置为我的元素,它工作正常并显示警告,它将在 Angular 7 版本中被弃用。

<textarea formControlName="questioning" [(ngModule)]="question.questioning" cols="70" rows="4"></textarea>

因此,我通过以下操作将值设置为表单控件,但元素未显示这些值。

setValue()
   this.editqueForm.setValue(user: this.question.user, questioning: this.question.questioning)

谁能告诉我如何设置值来挖掘反应形式。请给我建议。

【问题讨论】:

【参考方案1】:

可以使用patchValue 和setValue 来设置或更新响应式表单表单控件的值。但是,在某些情况下使用patchValue 可能会更好。

patchValue 不需要在参数中指定所有控件来更新/设置表单控件的值。另一方面,setValue 要求填写所有表单控件值,如果您的任何控件未在参数中指定,它将返回错误。

在这种情况下,我们将要使用 patchValue,因为我们只更新 userquestioning

this.qService.editQue([params["id"]]).subscribe(res => 
  this.question = res;
  this.editqueForm.patchValue(
    user: this.question.user,
    questioning: this.question.questioning
  );
);

编辑:如果你想做一些 ES6 的 Object Destructuring,你可能有兴趣这样做 ?

const  user, questioning  = this.question;

this.editqueForm.patchValue(
  user,
  questioning
);

哒哒!

【讨论】:

您能否详细分享一下setValuepatchValue 的不同之处以及为什么它会在这种情况下起作用。 是的,我实际上已经包含了它。很抱歉在我最初的编辑中含糊不清。 嗨@wentjun,它不起作用。不过,我的表格只是空的。它没有显示数据。 哦,你应该在subscribe中调用你的方法 我已经更新了我的答案。只是检查一下,this.question 包含一个值,对吗?尝试运行console.log(this.question)。它不是未定义的吗?【参考方案2】:

反应式表单中,有两种主要的解决方案来更新表单字段的值。

设置值:

在构造函数中初始化模型结构

this.newForm = this.formBuilder.group(  
   firstName: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(8)]],
   lastName: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(8)]]
);

如果要更新表单的所有字段:

this.newForm.setValue(
   firstName: 'abc',
   lastName: 'def'
);

如果要更新表单的特定字段:

this.newForm.controls.firstName.setValue('abc');

注意: 必须为 FormGroup 中的所有表单字段控件提供完整的模型结构。如果您错过任何属性或子集集合,则会引发异常。

补丁值:

如果您想更新表单的某些/特定字段:

this.newForm.patchValue(
   firstName: 'abc'
);

注意: 不必为 FormGroup 中的所有/任何表单字段控件提供模型结构。如果您错过任何属性或子集集合,那么它不会抛出任何异常。

【讨论】:

第三点应该更正为,如果要更新表单的特定字段:this.newForm.controls.firstName.setValue('abc');【参考方案3】:

试试这个。

editqueForm =  this.fb.group(
   user: [this.question.user],
   questioning: [this.question.questioning, Validators.required],
   questionType: [this.question.questionType, Validators.required],
   options: new FormArray([])
)

setValue() 和 patchValue()

如果你想设置一个控件的值,这将不起作用,因此你必须设置两个控件的值:

formgroup.setValue(name: ‘abc’, age: ‘25’);

有必要提到方法内部的所有控件。如果不这样做,就会抛出错误。

另一方面,patchvalue() 在这方面要容易得多,假设您只想将名称分配为新值:

formgroup.patchValue(name:’abc’);

【讨论】:

TAB,这不行,定义editqueForm时,“this.question”没有值。 我已经在我的订阅者中做到了:ngAfterViewInit(): void this.childDetailDS$.subscribe((data) => this.gDetailDS = data; this.cityPlaceForm = this.formBuilder。 group( cpCode: [this.gDetailDS.cpCode, Validators.required], cpName: [this.gDetailDS.cpName, Validators.required], 省份: [this.gDetailDS.province], status: [this.gDetailDS.status] , 版本号: [this.gDetailDS.versionNo] ); ); 不使用 ngAfterViewInit -是的,您不知道在 ngAfterViewInit 中是否有价值-,您必须在“订阅”中创建表单,请参阅我的答案【参考方案4】:

“通常”的解决方案是创建一个返回空 formGroup 或完整的 formGroup 的函数

createFormGroup(data:any)

 return this.fb.group(
   user: [data?data.user:null],
   questioning: [data?data.questioning:null, Validators.required],
   questionType: [data?data.questionType, Validators.required],
   options: new FormArray([this.createArray(data?data.options:null])
)


//return an array of formGroup
createArray(data:any[]|null):FormGroup[]

   return data.map(x=>this.fb.group(
        ....
   )

然后,在 SUBSCRIBE 中调用函数

this.qService.editQue([params["id"]]).subscribe(res => 
  this.editqueForm = this.createFormGroup(res);
);

小心!,您的表单必须包含 *ngIf 以避免初始错误

<form *ngIf="editqueForm" [formGroup]="editqueForm">
   ....
</form>

【讨论】:

【参考方案5】:

要为单个表单控件/单独分配值,我建议通过以下方式使用 setValue

this.editqueForm.get('user').setValue(this.question.user);

this.editqueForm.get('questioning').setValue(this.question.questioning);

【讨论】:

【参考方案6】:

使用patchValue() 方法有助于更新控件的子集。

setValue()
  this.editqueForm.patchValue(user: this.question.user, questioning: this.question.questioning)


来自 Angular 文档setValue() 方法:

错误当严格检查失败时,例如设置不存在的控件的值,或者您排除了控件的值

在您的情况下,对象缺少 optionsquestionType 控制值,因此 setValue() 将无法更新。

【讨论】:

以上是关于如何在 Angular 的反应式表单中设置表单控件的值的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Angular 7 响应式表单中设置 HTML Select Element 的选定值?

使用反应式表单在 Angular 中检查后,表达式发生了变化

如何在 Visual Studio 2017 中设置表单控件的工具提示属性

如何在 vue js 中设置输入表单控件默认聚焦,直到输入值?

Angular 反应式表单自定义控件异步验证

Angular 2:迭代反应式表单控件