Philip Mutua
Philip Mutua

Reputation: 6871

How to detect updated values in a reactive form and only send them as payload

I have an update component I want to only send the changed form values to some backend update endpoint. For some reason if I update only one form input the rest of the values appear. I had implemented a way to check empty form values and remove them from the payload object shown below in .ts file which works but now I want to only detect changed form values & only send them. Which convenient method should I use to resolve this?

TS File

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 FILE

<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>

Upvotes: 3

Views: 1358

Answers (2)

Dako patel
Dako patel

Reputation: 920

try this logic for get only updated value in reactive form !

   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;
}

hope it will usefull for all !

Upvotes: 1

Eduard Keilholz
Eduard Keilholz

Reputation: 933

You can bind events to each and every single control. You can also get the 'pristine' property from a control.

So a good idea would be to (for example) catch the changed event of the form and check each control for the pristine property. When pristine is true, the value is not changed. When false, the value IS changed.

You can use the form to loop through its controls so you can pretty much do this in an automated fashion.

Upvotes: 1

Related Questions