ウェブサイト検索

angular - リアクティブフォームで更新された値を検出し、それらだけをペイロードとして送信する方法


更新コンポーネントがあり、フォームの変更された値だけをバックエンドの更新エンドポイントに送信したいです。なぜか、一つのフォーム入力だけを更新すると、他の値も送信されてしまいます。空のフォーム値をチェックしてペイロードオブジェクトから削除する方法は実装しており、これは動作しますが、今回は変更されたフォーム値だけを検出してそれらだけを送信したいです。この問題を解決するために便利な方法は何でしょうか?

TSファイル

this.form = this.fb.group({
  business_name: new FormControl(''),
  business_activity: new FormControl(''),
  business_id: new FormControl(''),
  pin_number: new FormControl(''),
  activity_code: new FormControl(''),
  po_box: new FormControl(''),
  town: new FormControl(''),
  physical_address: new FormControl(''),
  plot_number: new FormControl(''),
  contact_person_name:  new FormControl(''),
  contact_person_phone:  new FormControl(''),
  applicantName: new FormControl(''),
  sub_county_name: new FormControl(''),
  ward_name: new FormControl(''),
  applicantPhone: new FormControl(''),
  licenseActivity: new FormControl(''),
  fee: new FormControl(''),
});

onClickUpdate(){
    const payload = this.form.value;
    // Remove empty string
    Object.keys(payload).forEach((key) => (payload[key] === '') && delete payload[key]);
    console.log(JSON.stringify(payload))

}

HTMLファイル

<form [formGroup]="form" class="add-new-license">
  <div class="controls-container row">
    <mat-form-field>
      <input
        type="text"
        formControlName="business_name"
        matInput
        placeholder="Business Name"
        [(ngModel)]="license.business.business_name"
      />
    </mat-form-field>

    <mat-form-field>
      <input
        type="text"
        matInput
        formControlName="business_id"
        placeholder="Business ID"
        [(value)]="license.business.business_id"
      />
    </mat-form-field>

    <mat-form-field>
      <input
        type="text"
        matInput
        formControlName="pin_number"
        placeholder="Pin Number"
        [(value)]="license.business.pin_number"
      />
    </mat-form-field>

    <mat-form-field>
      <input
        type="text"
        matInput
        formControlName="po_box"
        placeholder="Po Box"
        [(value)]="license.business.po_box"
      />
    </mat-form-field>

    <mat-form-field>
      <input
        type="text"
        matInput
        formControlName="town"
        placeholder="Town"
        [(value)]="license.business.town"
      />
    </mat-form-field>

    <mat-form-field>
      <input
        type="text"
        formControlName="physical_address"
        matInput
        placeholder="Physical Address"
        [(value)]="license.business.physical_address"
      />
    </mat-form-field>

    <mat-form-field>
      <input
        type="text"
        matInput
        formControlName="sub_county_name"
        placeholder="SubCounty"
        [(value)]="license.business.sub_county_name"
      />
    </mat-form-field>

    <mat-form-field>
      <input
        type="text"
        matInput
        formControlName="ward_name"
        placeholder="Ward"
        [(value)]="license.business.ward_name"
      />
    </mat-form-field>

    <mat-form-field>
      <input
        type="text"
        matInput
        formControlName="plot_number"
        placeholder="Plot Number"
        [(value)]="license.business.plot_number"
      />
    </mat-form-field>

    <mat-form-field>
      <input
        type="text"
        matInput
        formControlName="contact_person_phone"
        placeholder="Phone"
        [(value)]="license.contact_person_phone"
      />
    </mat-form-field>

    <mat-form-field>
      <input
        type="text"
        matInput
        formControlName="contact_person_name"
        placeholder="Contact Person Name"
        [(value)]="license.contact_person_name"
      />
    </mat-form-field>

    <!--
    <mat-form-field>
      <input type="text" matInput placeholder="Applicant Name" formControlName="applicantName">

    </mat-form-field> -->

    <!-- <mat-form-field id="business-name">
      <input type="text" matInput placeholder="Applicant Phone" formControlName="applicantPhone">

    </mat-form-field> -->

    <br />
    <mat-form-field matTooltip="Select license activity">
      <!-- <input type="text" matInput placeholder="License Activity" formControlName="licenseActivity"> -->
      <mat-label style="color: black">License Activity</mat-label>
      <mat-select formControlName="licenseActivity">
        <!-- <mat-option>None</mat-option> -->
        <mat-option
          id="schedule-options"
          *ngFor="let category of liquorCategories"
          [value]="category.id"
          matTooltip="{{ getCategoryToolTipData(category.name) }}"
        >
          {{ category.name }}</mat-option
        >
      </mat-select>
      <div
        *ngIf="submitted && f.licenseActivity.errors"
        class="invalid-feedback"
      >
        <div *ngIf="f.licenseActivity.errors.required">
          License Activity is required
        </div>
      </div>
    </mat-form-field>

    <mat-form-field matTooltip="select only liquor application fee.">
      <mat-label style="color: black">Fee</mat-label>
      <mat-select formControlName="fee">
        <mat-option *ngFor="let fee of fees" [value]="fee.id">
          {{ fee.description }}: {{ fee.amount }}
        </mat-option>
      </mat-select>
    </mat-form-field>
  </div>
  <div class="row" id="submit-btn-section">
    <button
      mat-raised-button
      (click)="onClickUpdate()"
      id="submit-button"
      matTooltip="submit information"
    >
      UPDATE LICENSE
    </button>
  </div>
</form>

回答 #1

リアクティブフォームで更新された値だけを取得するには、このロジックを試してみてください!

   getUpdatedValue(form: any) {

       var changedValues = {};

        Object.keys(form.controls)
            .forEach(key => {
                let currentControl = form.controls[key];

                if (currentControl.dirty) {
                    if (currentControl.controls)
                        changedValues[key] = this.getUpdatedValue(currentControl);
                    else
                        changedValues[key] = currentControl.value;
                }
            });

        return changedValues;
}

皆に役立つことを願っています!

回答 #2

すべてのコントロールにイベントをバインドすることができます。また、コントロールから「pristine」プロパティを取得することもできます。

ですので、良いアイデアは(例えば)フォームの変更イベントをキャッチして、各コントロールのpristineプロパティをチェックすることです。pristineがtrueの場合、値は変更されていません。falseの場合、値は変更されています。

フォームのコントロールをループするためにフォームを使用できるので、ほぼ自動的にこれを行うことができます。