技術

[Angular]リアクティブフォームのHTML側の記法

投稿日:

Angularのリアクティブフォームではtsファイル側でネストした構成を組むことができます。
HTMLファイルでもformGroupやformControlの名前を定義できるのですが、
tsファイルで定義した構成に合うようにしてあげる必要があります。

構成に誤りがあると、以下のようなエラーが出たりします。

ERROR Error: formControlName must be used with a parent formGroup directive.  You'll want to add a formGroup directive and pass it an existing FormGroup instance (you can create one in your class).

それでは例で見てみましょう。

htmlで構成を再現する

formGroupName、formControlName、formArrayNameの3種類をうまく使って構成を組み上げてあげましょう。
それぞれFormControl、 FormGroup、FormArrayにNameがついただけなのでわかりやすいですね。

例えば、tsファイルで以下のような構成で組んだ場合。

~~
formGroup: FormGroup;
roomMates: Array;

constructor( private fb: FormBuilder ){}

ngOnInit() {
  this.formGroup = this.fb.group({
    firstName: [''],
    lastName: [''],
    address: this.fb.group({
      street: [''],
      city: [''],
      state: [''],
      zip: ['111-1111']
    }),
    frends: this.fb.array([
      this.fb.control(''),
      this.fb.control('')
    ])
  });
}

テキストボックスではhtml側では以下のように書けばOKです。

<form [formGroup]="formGroup">
  <input type="text" formControlName="firstName">  // tsファイルでfirstNameとして設定したformControlと紐付け。
  <input type="text" formControlName="lastName"> 
  <div formGroupName="address">                    // tsファイルでaddressと設定したformGroupと紐付け。
    <input type="text" formControlName="street">   // ネストしたformControlはformGroupNameを設定した要素の中に配置
    <input type="text" formControlName="city"> 
    <input type="text" formControlName="state"> 
    <input type="text" formControlName="zip"> 
  </div>
  <div formArrayName="friends">
    <div *ngFor="let roomMate of roomMates; index as i" >
        <input type="text" formControlName="{{i}}"> 
    </div>
  </div>
</form>

なお、tsファイル側だけで設定するということもあると思いますが、
html側にformControlNameが足りなくてもエラーになりません。
formArrayNameやformGroupNameが足りなくとどうなるか知りませんが、多分エラーにならないと思います。

コンポーネントを分割した場合

子コンポーネントに切り分けてあげる場合、親と同等に構造を書いてあげる必要があります。
上記の例のaddressの中を分割したとします。

<form [formGroup]="formGroup">
  <input type="text" formControlName="firstName">  
  <input type="text" formControlName="lastName">
  <div formGroupName="address">
    <app-address-area [formGroup]="formGroup"></app-address-area> // address内をコンポーネント分割してformGroupを渡す。
  </div>
  <div formArrayName="friends">
    <div *ngFor="let roomMate of roomMates; index as i" >
      <input type="text" formControlName="{{i}}"> 
    </div>
  </div>
</form>

この場合、子コンポーネントでは以下のように書けばOKです。

<form [formGroup]="formGroup">
  <div formGroupName="address">
    <input type="text" formControlName="street">
    <input type="text" formControlName="city"> 
    <input type="text" formControlName="state"> 
    <input type="text" formControlName="zip"> 
  </div>
</form>

普通はformGroupName=”address”ごと分割する方が良いですが、
多少わかり安いかなと思い上記のように書いてみました。

-技術
-,

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

関連記事

no image

CSSのbackgroundで複数の背景色を設定してみる

こんにちは 仕事で複数の背景色を設定する機会がありましたので 今回はそのやり方を …

no image

[wordpress]contact form7で作ったformをコード内で呼び出す

こんばんは wordpressでformを作る時はcontact form7を使 …

no image

【ionic】Cannot read property ‘startTrackerWithId’ of undefined だとよ

どうも中田です。 GoogleAnalyticsプラグインを導入したのですが、A …

ブラウザでRailsのrouting設定を確認する

こんにちは Railsでroutingを確認する時、コマンドでrails rou …

no image

[Angular] router-outletの外で現在のurlを取得

こんにちは、コーテッグのこやまです。 Angularでapp.component …