web-dev-qa-db-ja.com

各テーブル行の反応フォーム

Angular 2を使用していて、各行のコントロールを個別に検証したいのですが、それを行う方法がありません。リアクティブフォームのみを使用して実行したいのですが、テンプレート駆動型のアプローチを使用しています。各<tr>。どんな助けでもありがたいです。以下は私のコードの構造です:

<tbody *ngFor="let single of allTeamDetails"                
       [ngClass]="{'alternate-row-color': $even}">
  <tr>
    <td class="td-data first-column">
      <input type="text" class="input-text form-control" 
             [value]="single.first_name">
    </td>
    <td class="td-data second-column">
      <input type="text" class="input-text form-control" 
             [value]="single.last_name">
    </td>
    <td class="td-data third-column">
      <input type="email" class="input-text form-control" 
             [value]="single.email">
    </td>
    <td class="td-data fourth-column">
      <select class="selection-dropdown width-80-percent" 
              [value]="single.user_role">
        <option *ngFor="let singleRole of allUserRole"      
                value="{{singleRole.name}}"> 
                {{setUserRoleAndType(singleRole.name)}}</option>
      </select>
    </td>
    <td class="td-data fifth-column" >
      <input type="password" class="input-text form-control">
    </td>
    <td class="td-data sixth-column" >
      <input type="password" class="input-text form-control">
    </td>
    <td class="td-data save-send-tm-data">
      <button class="btn save-user-details save-sub-account-details"                                                      
              type="button" data-toggle="tooltip" title="Save">
        <i class="fa fa-floppy-o" aria-hidden="true"></i>
      </button>
    </td>
    <td class="td-data save-send-tm-data">
      <button type="button"                                      
              class="btn save-user-details save-sub-account-details"  
              data-toggle="tooltip" title="Send Message"                       
              (click)="openSendMessageModal(single.email)">
        <i class="fa fa-envelope" aria-hidden="true"></i> 
      </button>
    </td>
  <tr>
</tbody>
8
GeniusGo

formArrayを使用します。あなたがすることは、複数のより小さなformGroupを含むformGroup(マスターフォーム)を作成することです。小さい各fromGroupsは、*ngForで繰り返されるものになります。

フォームは次のようになります。

<!--This is your master form-->
<form [formGroup]="teamForm">
  <!--Use formArray to create multiple, smaller forms'-->
  <div formArrayName="memberDetails">
    <div *ngFor="let single of allTeamDetails; let $index=index">
      <div [formGroupName]="$index">
        <div>
          <!--your field properties of every repeated items-->
          <input placeholder="First Name" type="text" formControlName="firstName" />
        </div>
        <div>
          <input placeholder="Last Name" type="text" formControlName="lastName" />
        </div>
      </div>
    </div>
  </div>
</form>

コンポーネントでは、angularのformBuilderを使用してフォームを作成することができます。

あなたのコンストラクタで:

  constructor(private formBuilder: FormBuilder) {
    this.teamForm = this.formBuilder.group({
      memberDetails: this.formBuilder.array([])
    });
  }

これで、繰り返しモデルのすべてのプロパティを初期化できます。次に、各フィールドの各バリデーターをカスタマイズできます。 HTMLのプロパティに対応するTypeScriptファイルのプロパティに注意してください。これらすべてをngOnInitで実行して、プロパティがレンダリングされる前にHTMLにバインドできるようにします。

  ngOnInit() {   
    this.teamForm = this.formBuilder.group({
      memberDetails: this.formBuilder.array(
        this.allTeamDetails.map(x => this.formBuilder.group({
          firstName: [x.first_name, [Validators.required, Validators.minLength(2)]],
          lastName: [x.last_name, [Validators.required, Validators.minLength(2)]]
        }))
      )
    })
  }

これらすべての後、検証メッセージの追加は非常に簡単です。このようにすることの利点は?

  1. 各インスタンスはそれ自体で単一のformGroupになるため、検証ロジックを非常に細かいレベルまでカスタマイズできます。

  2. 上記のポイントとして、小さな各フォームの各valueChangeを、各単一フィールドまでサブスクライブできます。たとえば、最初のチームメンバーの名のフィールドの変更をサブスクライブする場合は、次のようにします。

      this.teamForm
       .controls.memberDetails
       .controls[0] //get the first instance!
       .controls.firstName  //get the firstName formControlName
       .valueChange 
       .subscribe(x=>console.log('value changed!))
    
  3. マスターフォームを検証する場合は、イベントを検証することもできます。

あなたのためだけに plnkr を作成しました:)

19
CozyAzure