技術

[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 を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

関連記事

git_logo

[Git] どのコミットでバグが入ったか原因究明する方法【git blame】

こんにちは。さとうです。 今回はgitを使って、どのコミットでバグが入ったか原因 …

[AWS Cli] brew install awscli が失敗!

どうも中田です awsコマンドがないよーって言われたので、再度インストールするこ …

rails_logo

[Rails] image_tagを使わずにassets内の画像を指定する方法

こんにちは。さとうです。 今回はimage_tagを使わずにassets内の画像 …

no image

【AWS】nginx/rails/mysqlをインストール

どうも、中田です。 最近AWSにテストサーバを立ち上げて検証したり、 お客様に一 …

no image

【Rails】productionモードでCSSの画像が表示されない

どうも中田です。 css内で画像を設定して、productionモードで動かすと …