简体   繁体   中英

Disable/enable button based on change of value Angular

I have a form with different input fields including input[type="file"] and input[type="checkbox"]. I get values of input form fields with get request from backend and I store them in company variable.

ngOnInit(): void {
    this.generateForm();

    this.companyService.getCompany().subscribe((response: Company) => {
      this.company = response;

      this.settingsForm.setValue({
        ...this.company,
        certificateUrl: [this.company.certificateUrl],
      });
    });
  }

I first generate form and then get my response from get request so I could set my company variable to the response and set value of form based on values I got. The problem is I want to enable button in html whenever my form is valid and changed. So button should be disabled when no change is made based on previous value. For example: If we have field name with value 'myName' and I type into input 'my' button should be enabled because change is made comparing to previous value. If I type back 'myName' it should be disabled because value is the same as previous. Same should happen if field is empty and user types in something and for fields type file and checkbox.

This is how I'm currently trying to do it.

inputChanged: boolean = false

ngOnInit() {
    this.settingsForm.valueChanges.subscribe((currentValue) => {
      if (JSON.stringify(currentValue) !== JSON.stringify(this.company)) {
        this.inputChanged = true;
      } else {
        this.inputChanged = false;
      }
    });
}
////

 <button
          [disabled]="!inputChanged || !settingsForm.valid"
          class="btn btn-md text-light"
        >
          Save
        </button>

This is my form

<form class="mt-4" [formGroup]="settingsForm" (ngSubmit)="saveChanges()">
    <div class="row">
      <div class="col-6">
        <div class="form-group">
          <label class="form-label fw-bold">ID</label>
          <input
            formControlName="identificationNumber"
            type="text"
            class="form-control"
          />
        </div>
        <div class="form-group d-none">
          <label class="form-label fw-bold">Id</label>
          <input formControlName="id" type="text" class="form-control" />
        </div>
        <div class="form-group d-none">
          <label class="form-label fw-bold">Country</label>
          <input formControlName="country" type="text" class="form-control" />
        </div>

        <div class="form-group">
          <label class="form-label fw-bold"
            >P</label
          >
          <input formControlName="tin" type="text" class="form-control" />
 
        </div>
        <div class="form-group">
          <label class="form-label fw-bold">Name</label>
          <input formControlName="name" type="text" class="form-control" />
        </div>
      </div>
      <div class="col-6">
        <div class="form-group">
          <label class="form-label fw-bold">City</label>
          <input formControlName="city" type="text" class="form-control" />
        </div>

        <div class="form-group">
          <label class="form-label fw-bold">Address</label>
          <input formControlName="address" type="text" class="form-control" />
        </div>
        <div class="form-group">
          <label class="form-label fw-bold">Postal code</label>
          <input
            formControlName="postalCode"
            type="text"
            class="form-control"
          />
        </div>
        <div class="form-check ms-1">
          <label class="form-check-label fw-bold">Vat</label>
          <input
            formControlName="inVat"
            type="checkbox"
            class="form-check-input"
            [checked]="company?.inVat"
          />
        </div>
      </div>
    </div>

    <div class="row align-items-end justify-content-between">
      <div class="col-8">
        <app-file-upload
          [company]="company"
          formControlName="certificateUrl"
        ></app-file-upload>
      </div>

      <div class="col-4">
        <button
          [disabled]="!inputChanged || !settingsForm.valid"
          class="btn btn-md text-light"
        >
          Save changes
        </button>
      </div>
    </div>
  </form>

But it doesn't work. How can I fix this?

You could make use of other reactive Form attributes

Using pristine for example

A control is pristine if the user has not yet changed the value in the UI.

<button
  [disabled]="settingsForm.pristine || settingsForm.invalid"
  class="btn btn-md text-light"
  >Save</button>

if you need to be more specific in the control values, it becomes more tricky as comparing Javascript objects is not as trivial.

This question is a great deep dive

The reactive form should have a valid and touched attribute and could be used as following.

<button
  [disabled]="!settingsForm.touched || settingsForm.invalid"
  class="btn btn-md text-light">Save</button>

I found a solution using objectHash. First install it with npm i -D @types/hash.

import * as objectHash from 'object-hash';

this.settingsForm.valueChanges.subscribe((currentValue) => {
      if (objectHash.sha1(currentValue) !== objectHash.sha1(this.company)) {
        this.inputChanged = true;
      } else {
        this.inputChanged = false;
      }
    });

////
<button
    [disabled]="!inputChanged || !settingsForm.valid"
    class="btn btn-md text-light"
    >
    Save
</button>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM