Make sure to verify the status of ngmodel or forms to see if they are dirty or contain

In Angular, how can I determine if ngModel or form fields are dirty or have input without using formgroup?

I need to check if at least 5 of the input fields have a value or are considered dirty in order to display a message. How can I achieve this for 5 fields from DealFields or ngModel dealDispositionFormFields? Thank you.

#tscode

    class DealDispositionFormFields {
      dealName:string;
      summary:string;
      dealDispositionType: string;
      terminationPayment:number;
      effectiveDate: string;
      totalBrokerCommission: number;
      effectiveDateString: string;
      dealId: number;
}
    
    @Component({
      selector: 'app-deal-idle-disposition',
      templateUrl: './deal-idle-disposition.component.html',
      styleUrls: ['./deal-idle-disposition.component.css']
    })
    export class DealIdleDispositionComponent implements OnInit {
           
             ngOnInit(): void {   
                this.dealDispositionFormFields = new DealDispositionFormFields();
              }
        
        checkIf5FieldsAreDirty() {
        ...
        }

#html code

<div id="deal-form-container" *ngIf="isEditing">
        <div id="deal-form-wizard-top" *ngIf="dealDispositionFormFields.dealDispositionType === 'Buyout'">
          <mat-form-field appearance="fill">
            <mat-label>Deal Name</mat-label>
            <input 
              matInput
              [(ngModel)]="dealDispositionFormFields.dealName"
              [required]="isExistingDeal">
          </mat-form-field>
          <mat-form-field appearance="fill">
            <mat-label>Summary of Deal</mat-label>
            <textarea 
              matInput
              class="resize-none"
              [(ngModel)]="dealDispositionFormFields.summary"
              [rows]="5"
              [required]="isExistingDeal">
            </textarea>
          </mat-form-field>
          <mat-form-field appearance="fill">
            <mat-label>Termination Payment</mat-label>
            <input 
              matInput
              (keyup) = "computeBuyout()"
              mask="separator.0" 
              thousandSeparator=","
              [allowNegativeNumbers]="false"
              [(ngModel)]="dealDispositionFormFields.terminationPayment"
              [required]="isExistingDeal">
              <span matPrefix *ngIf="dealDispositionFormFields.terminationPayment">$</span>
          </mat-form-field>
          <mat-form-field appearance="fill">
            <mat-label>Effective Date</mat-label>
              <input matInput
                (dateChange)="computeBuyout()"
                [matDatepicker]="effectiveDate" 
                [(ngModel)]="dealDispositionFormFields.effectiveDate"
                [required]="isExistingDeal">
              <mat-datepicker-toggle matSuffix [for]="effectiveDate"></mat-datepicker-toggle>
              <mat-datepicker #effectiveDate></mat-datepicker>
          </mat-form-field>
          <mat-form-field appearance="fill">
            <mat-label>Total Broker Commission</mat-label>
            <input 
              matInput
              (keyup) = "computeBuyout()"         
              mask="separator.0" 
              thousandSeparator=","
              [allowNegativeNumbers]="false"
              [(ngModel)]="dealDispositionFormFields.totalBrokerCommission"
              [required]="isExistingDeal">
              <span matPrefix *ngIf="dealDispositionFormFields.totalBrokerCommission">$</span>
          </mat-form-field>
        </div>
      </div>

Answer №1

When working with ngModel, it's worth noting the dirty property as highlighted in this helpful response

To monitor changes, you can utilize the change or ngModelChange events on your inputs.

For instance, within your code snippet:

HTML

<mat-form-field appearance="fill">
            <mat-label>Deal Name</mat-label>
            <input 
              matInput
              [(ngModel)]="dealDispositionFormFields.dealName"
              [required]="isExistingDeal"
              (change)="checkIfDirty()">
</mat-form-field>

TS

   checkIfDirty() {
    let countDirtyValues = 0;
    Object.values(this.dealDispositionFormFields).map(value => {
      if (value) {
        countDirtyValues += 1;
      }
    });
    if (countDirtyValues >= 5) {
      // do something here
    }
  }

If seeking an alternative approach, consider that ngmodel is essentially a formControl instance. In such cases, opting for a reactive form, as outlined in the Angular documentation for formControl here, could offer a solution without necessarily needing a formGroup.

Answer №2

If you're looking for a robust solution for form validation in Angular, Reactive Forms are the way to go. They offer comprehensive functionality and are more user-friendly.

For detailed instructions on using reactive forms, refer to the official guide at: https://angular.io/guide/reactive-forms

In your component, you can define a FormGroup with controls as shown below:

@Component({
      selector: 'app-deal-idle-disposition',
      templateUrl: './deal-idle-disposition.component.html',
      styleUrls: ['./deal-idle-disposition.component.css']
})
export MyComponent implements OnInit {
  myForm: FormGroup;
  constructor() {
    // create the form
    this.myForm = new FormGroup({
      name: new FormControl('', [Validators.required]),
      age: new FormControl(0, [Validators.required, Validators.min(18)])
    });
  }
}

The API docs (https://angular.io/api/forms/FormControl) indicate that the FormControl class inherits from AbstractControl, which includes the dirty flag field. You can assess a control's state using this property:

const nameControl = this.myForm.get('name'); // or this.myForm.controls['name'];
if (nameControl.dirty) {
  // ...
}

Furthermore, you can observe changes in the control's value, similar to ngModel:

nameControl.valueChanges.subscribe((newValue) => {
  // ...
});

Similarly, you can monitor status changes of the control using:

nameControl.statusChanges.subscribe((newStatus) => {
  // ...
});

Be sure to explore the official guide and API documentation to gain insights into Angular's framework.

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

Utilizing Typescript to implement an interface's properties

After declaring an interface as shown below interface Base { required: string; } I proceeded to implement the interface in a class like this class MyClass implements Base{ method(): void { console.log(this.required); } } However, I ...

Error: global not declared in the context of web3

I've been attempting to integrate Web3 into my Ionic v4 project for some time now. However, I keep encountering errors when I try to serve the project. Specifically, I receive an error message stating that Reference Error: global is not defined. Cre ...

PrimeNG's Angular component pTree TreeNode

Is there a way in Angular to retrieve the positions of nodes within a TreeNode hierarchy based on their display order? I have data structured as TreeNode objects, which include children that can branch off further. How can I access these nodes according t ...

Troubleshooting: Angular.js error when Typescript class constructor returns undefined

I'm currently trying to create a simple TypeScript class, however I keep encountering an error stating this is undefined in the constructor. Class: class MyNewClass { items: string; constructor(){ this.items = 'items'; ...

I am looking to include an image URL in the JSON data of my Angular form and then send it to the server. The image URL will be retrieved from the server response

How can I upload an image URL to my Angular form as JSON data and send it to the server? The server needs to respond with the image URL after renaming the image. I need to retrieve the new image URL from the server, update my form with it, and then submit ...

The error message "Value property is not found on the FilterMetadata type in the PrimeNG table" indicates that there is an issue with accessing the 'value'

While transitioning a module from Primeng 7 to Primeng 11 in conjunction with Angular 11, everything seems to be running smoothly on ng serve with all functionalities working as expected. However, upon building the project, I encounter an unexpected error. ...

Use Angular's super.ngOnDestroy method for handling cleanup/unsubscribing

When it comes to unsubscribing / cleaning up from observables in Angular components (using ngOnDestroy), there are multiple options available. Which option should be considered the most preferable and why? Also, is it a good practice to include super.ngOnD ...

Undefined TypeScript Interface

Here's my situation: public retrieveConnections() : IUser[] { let connections: IUser[]; connections[0].Id = "test"; connections[0].Email = "asdasd"; return connections; } I know this might be a dumb question, but why is connecti ...

Angular - Evaluating the differences between the object model and the original model value within the view

To enable a button only when the values of the 'invoice' model differ from those of the initial model, 'initModel', I am trying to detect changes in the properties of the 'invoice' model. This comparison needs to happen in th ...

Angular encountering issues with loading external JavaScript files due to the error: ENOENT - indicating that the specified file or directory does

I am attempting to incorporate a bootstrap template into Angular. The template requires some external JavaScript and CSS files that need to be linked. I have placed these files in the assets folder and referenced them in the styles and scripts arrays of an ...

A simple guide on how to send an Angular component to the Nebular dialog service

My current project involves creating a web dialog in Angular6 using Nebular components. Initially, I used the method of passing an <ng-template> reference in the following manner: openAddDialog = (dialogTemplate: TemplateRef<any>) => { ...

What is the best way to retain multiple values passed through Output() and EventEmitter() in Angular?

In my Angular application, I have implemented custom outputs to transmit user-selected values between components. Currently, the functionality allows for the selected value from checkbox items to be sent to a sub-component, where it is displayed in the con ...

Condition for rendering child components using Angular guard

I am faced with a scenario where I have 3 children in a parent component and I need to render them based on specific conditions: If my variable is equal to zero, the welcomePage should be rendered If the variable falls between one and ten, then the interm ...

Angular reactive form pattern validator restricts input to text, digits, and certain special characters

I am currently working with Angular 10 and reactive forms. I have a requirement where an input field should only accept letters, numbers, and the special characters "_" and "-". I have attempted to allow letters and numbers using the following code: Valid ...

TS1056 Error: Accessors can only be utilized with ECMAScript 5 or newer versions targeted

I'm currently working on a SharePoint framework project that has the following folder layout: One of the directories is named dataaccess and contains a webpart factory method. The file Sharepointdataprovider.ts includes this code snippet: import { ...

Filtering out specific properties from an element within a JavaScript forEach loop

const findBloodType = bloodCodeArray.find(bloodCode => bloodCode.code.toUpperCase() === bloodType.toUpperCase()).code; In my Angular code, I am trying to retrieve just the 'code' property of the 'bloodCode' element using a callback ...

The click event in an Angular 6 loop is not being activated

When the Test is clicked, the function should be invoked. However, nothing happens when I click on it. Here is the HTML component code: <div class="row m-0 justify-content-between" *ngFor="let i of k[currentk]?.details | keys"> <div (click ...

Having difficulty executing unit testing in Angular 5 - ng test

When I run ng test, I encounter an error that says "Uncaught TypeError: Zone.__load_patch is not a function". I investigated the source code using the debugger console in Chrome, and it points to an error in ../zone.js/dist/async-test.js_global. It was w ...

"Unindexing data in Angular: A step-by-step guide

Can someone help me figure out how to delete an item by index in Angular? I have a parameter and a remove button, but when I tried putting my parameter inside the remove button it didn't work. How can I fix this? deleteRowFiles(rowIndex: number){ th ...

typescript array filter attributes

I encountered a situation where I had 2 separate arrays: items = [ { offenceType:"7", offenceCode:"JLN14", }, { offenceType:"48", offenceCode:"JLN14", } ]; demo = [ { offenceCode: 'JLN14&apo ...