iT邦幫忙

0

angular - FormArray Cannot find control with path

  • 分享至 

  • xImage

各位板上的大大好,小弟最近剛使用Angular的Control Value Accessor開發一些專案,對於Angualr的Reactive Forms中的FormArray的綁定遇到了一些問題。

我在父Component中給訂了初始值:

import { Component, OnInit } from '@angular/core';
import {
  FormArray,
  FormBuilder,
  FormControl,
  FormGroup,
} from '@angular/forms';

@Component({
  selector: 'app-root',
  template: `
    <form [formGroup]="myForm">
      <div class="form-group">
        <label>Name Array: </label>
        <app-my-sub-array-component 
            formControlName="nameArray"
        ></app-my-sub-array-component>
      </div>
    </form>
    <p>Form value: {{ myForm.value | json }}</p>
  `,
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  title = 'control-value-accessor';

  myForm: FormGroup;
  constructor(private fb: FormBuilder) {}

  ngOnInit(): void {
    this.initFormGroup();
  }

  private initFormGroup(): void {
    this.myForm = this.fb.group({
      nameArray: new FormControl([{street: 'street1', city: 'city1'}])
    });
  }
}

[{street: 'street1', city: 'city1'}]透過CVA傳遞給子Component(app-my-sub-array-component),在子Component中也確實有收到,但是對於forms綁定的時候卻出了狀況

import { Component, OnInit, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR, AbstractControl, FormGroup, FormBuilder, FormControl, FormArray } from '@angular/forms';

@Component({
  selector: 'app-my-sub-array-component',
  template: `
  <form [formGroup]="formGroup">
    <ng-container formArrayName="addressList">
      <ng-container *ngFor="let item of addressList.controls"; let i = index; [formGroupName]="i">
          <label>Street: </label>
          <input [formControlName]="street" type="text"/>
          <label>City: </label>
          <input [formControlName]="city" type="text"/>
      </ng-container>
    </ng-container>
  </form>
  `,
  styleUrls: ['./my-sub-array-component.component.css'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => MySubArrayComponentComponent),
      multi: true
    }
  ]
})
export class MySubArrayComponentComponent implements ControlValueAccessor {
  formGroup: FormGroup;
  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.formGroup = this.fb.group({
      addressList: this.fb.array([])
    });
  }

  get addressList() {
    return this.formGroup.get('addressList') as FormArray;
  }

  writeValue(value): void {
    const addressList = this.formGroup.get('addressList') as FormArray;
    if (value !== undefined && Array.isArray(value)) {
      value.forEach(item => {
        addressList.push(this.fb.group({
          street: new FormControl(item.street),
          city: new FormControl(item.city)
        }));
      });
    }
  }
  registerOnChange(fn: (_: any) => void): void{
    this.formGroup.valueChanges.subscribe(fn);
  }
  registerOnTouched(fn: (_: any) => void): void{
  }
}

https://ithelp.ithome.com.tw/upload/images/20201122/20124767IeBriVbuU6.png

不知道是綁定的方式出了問題,一直無法將畫面中的input綁定到forms中,希望各位大大可以給我一點方向,謝謝各位。

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

0
tonykcho
iT邦見習生 ‧ 2020-11-24 00:53:47

我最近也在學習Angular, 應該可以交流一下

  1. let i = index 請寫在*ngFor內
  2. 請留意甚麼時候該使用 Model Binding []

例如: [formControlName]="street" 和 formControlName="street" 的分別

前者Angular 會找class裏的 street 數值, 而class裏沒有定義street 因此會變成 formControlName="null"

後者則是直接給"street"的 value

Code

<form [formGroup]="formGroup">
    <ng-container formArrayName="addressList">
      <ng-container *ngFor="let item of addressList.controls; let i = index" [formGroupName]="i">
          <label>Street: </label>
          <input formControlName="street" type="text"/>
          <label>City: </label>
          <input formControlName="city" type="text"/>
      </ng-container>
    </ng-container>
</form>
0
hughc
iT邦新手 4 級 ‧ 2021-08-20 18:11:30

沒錯,差不多就是樓上說的原因。

let index那邊怪怪的。

不過這裡會報錯的原因應該是formControlName綁定的是FormGroup裡面的key。
所以它應該要是字串,但你用了屬性綁定,你並沒有宣告該屬性的變數在FormArray下面,所以出錯。

把那邊的[]拿掉試試吧!

<ng-container *ngFor="let item of addressList.controls; let i = index" [formGroupName]="i">
  <label>Street: </label>
  <input formControlName="street" type="text" />
  <label>City: </label>
  <input formControlName="city" type="text" />
</ng-container>

我要發表回答

立即登入回答