首页 > 解决方案 > 使用角度中的 patchValue 将值修补到复选框

问题描述

我正在尝试重新使用 mycreate-form来编辑表单的值。我的复选框在创建表单时按要求工作。当我单击编辑表单时,这些值不会修补到我的复选框。以下是我尝试过的代码:

<div class="form-row">
  <div class="form-group col-sm-6">
    <label>Authorized To</label>
    <br>
    <label *ngFor="let choice of authorized; let i=index">
      <input type="checkbox" [value]="choice" (change)="onCheckChange($event)" [checked]="checkedVal"
          formArrayName="authorized" type="checkbox[class.invalid]="! formGrowLicense.controls['authorized'].valid && formGrowLicense.controls['authorized'].touched ">
                            {{choice}}
     </label>
    <div *ngIf="!formGrowLicense.controls['authorized'].valid && (formGrowLicense.controls['authorized'].touched || isSubmitted)">
      <div class="invalid-feedback" style="display: block;">Please enter authorized to</div>
    </div>

  </div>
</div>

ts

authorized: any = ['CULTIVATE', 'HARVEST', 'PROCESS']; //displaying list of checkbox
constructor() {
  this.formGrowLicense = this.formBuilder.group({
      businessName: ['', Validators.required], 
      authorized: new FormArray([], [Validators.required])
       });
   } 
 getGrowLicense(id) {
    this.httpService.getGrowLicenseById(id).subscribe(
      response => {
        this.patchGrowLicense(response);
        this.checkedVal = response.authorisedTo; // tried storing response in this variable  ['CULTIVATE','HARVEST']
      },

      (err: any) => console.log(err)
    );
  }
patch(licenseObj){
    this.formGrowLicense.patchValue({
      businessName:licenseObj.companyName,
      authorized: licenseObj.authorisedTo, // here i'm getting response ['CULTIVATE','HARVEST']. Need to patch these two values as checked in checkbox
      });
    }

 onCheckChange(event) {
    this.formArray = this.formGrowLicense.get(
      'authorized'
    ) as FormArray;

    /* Selected */
    if (event.target.checked) {
      console.log(event.target.value);
      // Add a new control in the arrayForm
      this.formArray.push(new FormControl(event.target.value));
    } else {
      /* unselected */
      // find the unselected element
      let i = 0;

      this.formArray.controls.forEach((ctrl: FormControl) => {
        if (ctrl.value == event.target.value) {
          // Remove the unselected element from the arrayForm
          this.formArray.removeAt(i);
          return;
        }

        i++;
      });
    }
  }

标签: angulartypescript

解决方案


你有一个 FormControls 的 FormArray,它接受值 true/false 和接收的值以及固定数组中的字符串数组,所以首先你需要将接收到的数组转换为 true/false 数组

第一种方法

首先,我们将创建一个带有 formArray 的表单。与往常一样,我们可以管理一个表单数组,我们需要创建一个 getter 来返回我们的 formArray

  //our getter formArray
  get authorizedArray()
  {
    return this.formGrowLicense.get('authorized') as FormArray
  }

  ngOnInit()
  { //we create the formArray
    this.formGrowLicense=new FormGroup({
      businessName:new FormControl(),
      authorized:new FormArray(this.authorized.map(x=>new FormControl(false)))
    })
  }

看到创建 formArray 的方法是使用new FormArray(..here and array of formControls..). 创建formControls的formArray的方法是将数组“this.autorized”的每个元素“映射”到FormControl。

为了管理一系列输入,我们使用这个 .html

<form [formGroup]="formGrowLicense">
    <input formControlName="businessName">
    <!--we use formArrayName in a div-->
    <div formArrayName="authorized">
        <!--we iterate over autorizedArray.controls
           remember our getter of the formArray? -->
        <div *ngFor="let control of authorizedArray.controls;let i=index">
            <!--we use [formControlName]=i -->
            <label><input type="checkbox"  [formControlName]="i">{{authorized[i]}}</label>
        </div>
    </div>
</form>

与往常一样,我们在 .html 中使用(仅用于检查)检查是否一切正常

<pre>
  {{formGrowLicense?.value|json}}
</pre>

看看我们如何遍历 formArrayControls,并使用索引,在标签中显示 authorized[i]

好吧,我们还知道如何控制表单数组,所以下一个问题:我们如何为 formArray 提供值?

请记住,我们收到了一些喜欢,例如

{
  businessName:'my business name'
  authorized:['CULTIVATE', 'PROCESS']
}

当我们收到数据中的值时,我们可以使用一些类似

   this.formGroupLicense.patchValue(
    {
     businessName:data.businessName,
     authorized:this.authorized.map(x=>data.authorized.indexOf(x)>=0)
    }

了解如何在 3 个元素的数组中使用 0、1、2 或 3 个元素转换“data.authorize”和数组,该数组取值为 true 或 false

好吧,我们需要做的最后一项工作是,在提交时,使用 formArray 的值(例如 [true,false,false] 来获取字符串数组

submit(form)
{
   if (form.valid)
   {
        const data={
           businessName:form.value.businessName
           authorize:form.value.authorized.map(
              (x,index)=>x?this.authorized[index]:null)
              .filter(x=>x)
        }
        console.log(data) //<--here we has the data we send to the service
   }
}

是的,我们映射[true,false,false]['CULTIVATE',null,null]和过滤器,只需要不为空的元素['CULTIVATE']

好吧,使用 pathValue 是可以的,但是为什么我们不创建一个函数来返回带有我们想要的数据的 formGroup

createFormGroup(data:any=null)
{
    data=data||{businessName:null,authorize:[]}
    return new FormGroup({
      businessName:new FormControl(data.businessName),
      authorized:new FormArray(this.authorized
        .map(x=>new FormControl(data.authorized.indexOf(x)>=0)))
    })
}

所以,当我们收到数据时,我们唯一需要的就是使用

  this.formGroupLicense=this.createFormGroup(data)

第二种方法

我们有一个像

    this.formGrowLicense=new FormGroup({
      businessName:new FormControl(),
      authorized:new FormControl()
    })

是的!授权是一个存储数组的 FormControl。如果看到材质多勾选就是这种方法。为此,您可以使用自定义 formControl检查此SO 。让我解释一下(我不想要 customFormControl)

我们有一个辅助数组,其中包含两个属性“名称”和“值”,我们希望得到一些类似的属性,例如

authorizedAux: any = [{name:'CULTIVATE',value:true}, 
                      {name:'HARVEST',value:false},
                      {name:'PROCESS',value:true}]

所以我们添加一个函数

  setAutorized(data: string[]) {
    this.authorizedAux = this.authorized.map(x => ({
      name: x,
      value: data.indexOf(x) >= 0
    }));
  }

另一个函数解析

  parse() {
    const result=this.authorized
      .map((x, index) => (this.authorizedAux[index].value ? x : null))
      .filter(x => x);
    return result.length>0?result:null
  }

然后我们可以有一个使用 ngModel、ngModelChange 和 ngModelOptions 来更改 FormControl 值的 html

<form [formGroup]="form">
    <input formControlName="businessName">
        <div *ngFor="let control of authorizedAux">
            <label>
        <input type="checkbox"  
            [ngModel]="control.value"
            (ngModelChange)="control.value=$event;form.get('authorized').setValue(parse())"
            [ngModelOptions]="{standalone:true}"
      >{{control.name}}</label>
        </div>
</form>

请记住,当收到数据时,我们需要调用函数 setAutorized

查看stackblitz中的两种方法


推荐阅读