web-dev-qa-db-ja.com

Angular 2動的なネストされたフォーム

基本的に、下の図のようにオブジェクトがネストされた動的なフォームを作成します。 Angular 2 Nested Form Example

  • ペイオフはモデルの配列にあります
  • 必要に応じてペイオフを追加/削除できるはずです。
  • フォームは、基になるフォームコントロールとモデルを同期する必要があります
  • ペイオフの数は任意であり、モデルからフォームにロードする必要があります

Angular 2でこれを行う方法として見つけることができる実用的な例はありませんが、これはAngular 1。


以下は元の質問ですが、説明のために更新してあります(上記を参照):

最初に、Angular 2 rc.2の新しいバージョンが数日前にリリースされたばかりであることを知っていることを指摘したかったので、動的なネストされたフォームを作成するためのコードいくつかは変更された可能性がありますが、これを理解するのに十分なドキュメントがありません。

Angular 2の最新バージョンでは、現在rc.1を使用していますが、rc.2に更新する予定です)このようなフォームを作成する必要があります(疑似コード見る):

<form [ngFormModel]="form" (ngSubmit)="onSubmit()">
  <input type="text" ngControl="name">

  <div *ngFor="let expense for expenses; let i = index;" control-group="expenses">
    <input type="text" ngControl="expense.amount" [(ngModel)]="myModel.expenses[i].amount"> 
    <input type="checkbox" ngControl="expense.final" [(ngModel)]="myModel.expenses[i].final"> 
  </div>

  <a class="button" (click)="addExpenseControl()">Add</a>
  <a class="button" (click)="deleteExpenseControl()">Delete</a>
</form>

したがって、上記の疑似コードは機能しませんが、ドキュメントがないために正直に言うと、このようなものを配線する方法を理解できません。入れ子になったControlGroupについてのチュートリアルはいくつかありますが、コントロールグループを動的に追加および削除できる必要があるため、これはここでは当てはまりません。また、それらをモデルと同期できるようにする必要もあります。

私はこれを見つけました plunkr ここにAngularチームがフォームへのコントロールの追加を許可するチームによって提供されますが、これはの追加/削除ではありません) ControlGroup、むしろそれはControlArrayを使用していて、それがここに当てはまるかどうかわかりませんか?

新しいモデルベースのAngular 2フォームを使用することに非常に精通していますが、リソースを適切にネストするためにリソースを把握して(動的に!)、このネストされたデータをメインに結び付けますフォームモデル。ビュ​​ーでネストされたコントロールをどのように参照しますか?上記の疑似コードは近いですか?コントローラからコードを投稿しますが、ネストされた経費(ControlGroup)に関しては、どこから始めればよいかわかりません。 ??)上記...

14
FireDragon

Angular 2でフォームがまだ変化しているようで、これに似た他の例は見たことがありません(ただし、非常に一般的な使用のようです) -場合)。

これはplunkrです Angular2 RC3を使用した実例の例。

私は更新されたAngularからの2つのフォームコード このドキュメント を使用しています。

app.component.ts(フォームを含む):

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

@Component({
  selector: 'my-app',
  templateUrl: 'app/app.html',
  directives: [REACTIVE_FORM_DIRECTIVES],
  providers:  []
})
export class AppComponent {
  form: FormGroup;
  myModel:any;

  constructor() {
    // initializing a model for the form to keep in sync with. 
    // usually you'd grab this from a backend API
    this.myModel = {
      name: "Joanna Jedrzejczyk",
      payOffs: [
        {amount: 111.11, date: "Jan 1, 2016", final: false},
        {amount: 222.22, date: "Jan 2, 2016", final: true}
        ]
    }

    // initialize form with empty FormArray for payOffs
    this.form = new FormGroup({
      name: new FormControl(''),
      payOffs: new FormArray([])
    });

    // now we manually use the model and Push a FormGroup into the form's FormArray for each PayOff
    this.myModel.payOffs.forEach( 
      (po) => 
        this.form.controls.payOffs.Push(this.createPayOffFormGroup(po))
    );
  }

  createPayOffFormGroup(payOffObj) {
    console.log("payOffObj", payOffObj);
    return new FormGroup({
      amount: new FormControl(payOffObj.amount),
      date: new FormControl(payOffObj.date),
      final: new FormControl(payOffObj.final)
    });
  }

  addPayOff(event) {
    event.preventDefault(); // ensure this button doesn't try to submit the form
    var emptyPayOff = {amount: null, date: null, final: false};

    // add pay off to both the model and to form controls because I don't think Angular has any way to do this automagically yet
    this.myModel.payOffs.Push(emptyPayOff);
    this.form.controls.payOffs.Push(this.createPayOffFormGroup(emptyPayOff));
    console.log("Added New Pay Off", this.form.controls.payOffs)
  }

  deletePayOff(index:number) {
    // delete payoff from both the model and the FormArray
    this.myModel.payOffs.splice(index, 1);
    this.form.controls.payOffs.removeAt(index);
  }
}

上記で、新しいFormGroupオブジェクトをFormArrayオブジェクトであるform.controls.payOffs配列に手動でプッシュしていることに注意してください。

app.html(フォームhtmlを含む):

  <form (ngSubmit)="onSubmit()" [formGroup]="form">

    <label>Name</label>
    <input type="text" formControlName="name" [(ngModel)]="myModel.name" placeholder="Name">

    <p>Pay Offs</p>
    <table class="simple-table">
      <tr>
        <th>Amount</th>
        <th>Date</th>
        <th>Final?</th>
        <th></th>
      </tr>
    <tbody>
      <tr *ngFor="let po of form.find('payOffs').controls; let i = index">
        <td>
          <input type="text" size=10 [formControl]="po.controls.amount" [(ngModel)]="myModel.payOffs[i].amount">
        </td>
        <td>
          <input type="text" [formControl]="po.controls.date" [(ngModel)]="myModel.payOffs[i].date">
        </td>
        <td>
          <input type="checkbox" [formControl]="po.controls.final" [(ngModel)]="myModel.payOffs[i].final">
        </td>
        <td>
          <button (click)="deletePayOff(i)" style="color: white; background: rgba(255, 0, 0, .5)">x</button>
        </td>
      </tr>
    </tbody>
    <tr>
      <td colspan="4" style="text-align: center; padding: .5em;">
        <button (click)="addPayOff($event)" style="color: white; background: rgba(0, 150, 0, 1)">Add Pay Off</button>
      </td>
    </tr>
    </table>

  </form>

HTMLフォームでは、次のようなステートメントを使用して入力のモデルにフォームをリンクします。

... [formControl]="po.controls.amount" [(ngModel)]="myModel.payOffs[i].amount" ...
16
FireDragon