Strategies for monitoring for state changes in Angular 4/6

I am currently working on designing a webpage for account information. This web page will have 4 pre-filled fields - given name, family name, username, and email. There will also be a common save button at the bottom of the form. Users should be able to change any field by selecting the respective input field. I want the save button to only be enabled if the user makes changes to any of the fields. Is there a way to track state changes in this scenario? Below is a snippet of my code:

 <mat-card-content>
    <div class="form-group">
      <mat-form-field class="simple-form-field-50">
        <input matInput placeholder="Given name" name="givenName" formControlName="givenName">
      </mat-form-field>
      <mat-form-field class="simple-form-field-50">
        <input matInput placeholder="Family name" name="familyName" formControlName="familyName">
      </mat-form-field>
      <br>
      <mat-form-field>
        <input matInput placeholder="Email" name="email" formControlName="email">
      </mat-form-field>
      <br>
      <button
          [disabled]="waiting"
          class="simple-form-button" 
          color="primary" 
          mat-raised-button 
          type="submit" 
          value="submit">
        Save
      </button> 
    </div>
</mat-card-content>

This is the output generated by my code:

Answer №1

When utilizing a Reactive Form, you have the option to utilize valueChanges on the FormGroup.

Since this is an Observable, you can use subscribe to establish a boolean variable that will toggle the button's enablement in the template.

...

@Component({...})
export class AppComponent  {
  form: FormGroup;
  disableButton = true;

  ngOnInit() {
    ...

    this.form.valueChanges.subscribe(changes => this.disableButton = false);

  }
}

In your HTML template:

<form [formGroup]="form">
  ...
  <button [disabled]="disableButton">Submit</button>
</form>

UPDATE:

If you want to disable the button when values stay the same, compare the current and previous form values:

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  form: FormGroup;
  disableButton = true;

  userValue = {
    firstName: 'John',
    lastName: 'Doe',
    email: '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2d47424543034942486d4942404c4e4443034e4240">[email protected]</a>' 
  }

  ngOnInit() {
    this.form = new FormGroup({
      firstName: new FormControl(),
      lastName: new FormControl(),
      email: new FormControl()
    });
    this.form.patchValue(this.userValue);
    this.form.valueChanges.subscribe(changes => this.wasFormChanged(changes));
  }

  private wasFormChanged(currentValue) {
    const fields = ['firstName', 'lastName', 'email'];

    for(let i = 0; i < fields.length; i++) {
      const fieldName = fields[i];
      if(this.userValue[fieldName] !== currentValue[fieldName]) {
        console.log('Came inside');
        this.disableButton = false;
        return;
      }
    }
    this.disableButton = true;
  }

}

NOTE: StackBlitz has been updated correspondingly.

To see a Functional Sample StackBlitz as reference.

Answer №2

function handleInputChange(value : string ){  
console.log(value );}
<input matInput placeholder="example" name="example" formControlName="exampleNM" (input)="handleInputChange($event.target.value)">

Answer №3

Have you heard of the concept known as Dirty Check?

If you're looking for more information, check out this helpful answer on Stack Overflow:

Interested in learning about Template-Driven Forms? Here's a guide to get you started: https://angular.io/guide/forms

Or maybe you'd prefer to delve into the world of Reactive Forms? This guide will point you in the right direction: https://angular.io/guide/reactive-forms

Curious about the differences between these two concepts? Check out this informative article:

I hope you find these resources helpful.

Answer №4

If I were to approach this situation, here is what I would do:

  form: FormGroup;
  enableSubmission = false;
  originalData: any;

  ngOnInit() {
    this.form = new FormGroup({
      control: new FormControl('Value')
    });

    this.originalData = this.form.controls['control'].value; // store the original data in a variable

    this.form.valueChanges.subscribe(changes => {
      if (this.originalData == changes.control) {  
        this.enableSubmission = false;
      }
      else {
        this.enableSubmission = true;
      }
    });
}

VIEW EXAMPLE

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Updating the parent page host within a cross-domain iframe: issues encountered in Firefox and Chrome browsers

I am encountering an issue with my iframe app where I am receiving an alert indicating "-error" in Chrome related to top.location.href. jQuery.ajax({ type : 'get', url : 'check_if_fb_data_set.php', success ...

"Doubling Up: The Art of Adding Elements to a Polymer

I am currently working on a to-do application using Polymer 2.0. One issue I'm facing is that when I add a note, it adds it as expected. However, when I try to add another note, it duplicates the notes in the array. I am having difficulty pinpointing ...

I am unable to utilize the outcome of a custom hook within a function or within an effect hook

I've developed a unique custom hook that retrieves a list of individuals File: persons.hooks.ts import {useEffect, useState} from "react"; import Person from "../../models/person/Person"; const usePersons = () => { const ...

What is the best way to send a reply from a GET request query on the server side of an express application?

Currently, I am utilizing a query to interact with a Postgres database in order to save the result into a variable within a GET request on the server-side of an Express application. Although my query successfully returns the desired issueID when executed ...

Manipulating an SVG graphic's attributes by linking them to an external geometry in Three.js

Delving into the world of Three.js, I've embarked on a project to design a 3D kit creator for my college assignment. Through my study, I've grasped the basics of setting up scenes, scene objects, geometries, materials, and textures. I've r ...

React App with Material UI V1-beta Integration

I just installed the Create React App example from Material-UI.com. curl https://codeload.github.com/callemall/material-ui/tar.gz/v1-beta | tar -xz --strip=2 material-ui-1-beta/examples/create-react-app Upon installation, I encountered the following erro ...

Filtering JavaScript arrays based on a variety of property combinations

My array structure is as follows: [{ id: 1, name: 'Stephen', Team: { name: 'Lion', color: 'blue' }, skills: ['allrounder', 'middleorder'] }, { id: 2, name: 'Daniel', Team: ...

Is it possible for issues to arise when serving a web app using the "Globals" module in the Mean Stack?

Looking to transfer a variable (a constructed filename) from one file to another within an API can be quite challenging. One solution that comes to mind is utilizing globals, but with my current code structure, it seems like the only viable option. To addr ...

Error message: When the mouse hovers over, display the chart(.js) results in TypeError: t is

I encountered a persistent error that I just can't seem to resolve. My goal is to showcase a chart using Chart.js when the mouse hovers over the canvas. However, upon hovering over the canvas, I keep getting a TypeError: t is null error. Error: { ...

Relocate the resizable handles in jQuery outside of the div elements

I currently have 3 nested divs. Using jQuery $(function() { $("#div1").resizable({ handles: "n, e, s, w, nw, ne, sw,se" }); $("#div1").draggable(); }); Within the HTML structure <div id="div1" style="left: ...

What is the best way to add a color swatch image using Javascript?

I'm facing a challenge in Shopify where I need to assign corresponding background images to color swatches. Currently, my icons are set up with the correct links for each color, but they are missing their respective images, similar to this example. I ...

Troubleshooting encoding problems with Google Cloud's Speech-to-Text API using Node.js

I'm currently working on a project that involves capturing audio from a user's microphone and sending it to a server for translation using Google's Speech-to-Text API. I am utilizing navigator.mediaDevices.getUserMedia() to access the audio, ...

During development, getStaticPaths and getStaticProps successfully function, however, the prop during build time becomes undefined

I am currently working on developing an eCommerce platform utilizing Next.js. One of the challenges I encountered was in the product page where dynamic routes are used. Specifically, I implemented getStaticProps to fetch the product and getStaticPaths to g ...

Utilize jQuery to extract various input/select box values and compile them into an array for submission using .ajax()

I am currently facing an issue with dynamically generated forms using PHP and updated with jQuery's .appendTo() function as visitors interact with it. My main goal is to collect all input text and select box values from the current form and submit the ...

Using an external call to trigger the revert method in jQuery UI

My draggable event setup looks like this: $(ids.label).draggable({ containment: ids.wrapper, revertDuration: 100, revert: function(event) { $(this).data("draggable").originalPosition = { top: $(this).data('origionalTo ...

CSS3 Transition effects are applied immediately to duplicated elements

My dilemma lies in applying CSS3 Transitions to elements by introducing a new class. Markup <div id="parent"> <div class="child"> </div> </div> CSS .child { background: blue; -webkit-transition: background 4s; ...

Issue with AJAX POST request: PHP failing to establish session

I would like to pass the element's id to PHP and create a session for it. This snippet is from a PHP file: <?php $sql = "SELECT id FROM products"; $result = mysqli_query($con,$sql); while($row = mysqli_fetch_array($result)) { ?> <tr cl ...

Tips for resolving Circular dependency issue in node.js?

While working on a post request, I encountered an issue with the code below: try{ const _id = await db.collection('UserInformation').insertOne(userObj); await db.collection('LoggedInUser').updateOne({ userId: _id }, { '$set&ap ...

How to create a custom Error page in Next.js using TypeScript

How do I create an Error page in Next.js using Typescript? I attempted the following: interface ErrorProps { statusCode: number; } function Error({ statusCode }: ErrorProps) { return ( <p> {statusCode ? `An error ${statusCode} ...

Is there a way to eliminate the header and footer from a Flutter WebView?

Here is the code snippet I tried to implement: I found a video tutorial by Joannes Mike on YouTube demonstrating how to remove the header and footer in Flutter WebView. However, it seems that Flutter has updated their library and the functions no longer w ...