The Angular form fails to detect when inputs are populated and does not display the mat-error message

The issue arises when the field is filled, but mat-errors indicate that input is required despite being entered. Without "

if (this.addInvoiceForm.invalid) {return;"

Everything else functions correctly

Provided HTML: `

<form method="POST" [formGroup]="addInvoiceForm" (ngSubmit)="addData()">
  <div class="formularz" *ngFor="let item of items">
    <mat-form-field >
      <mat-label>Name</mat-label>
      <input type="text" matInput formControlName="name"  [formControl]="item.nameFormControl" maxlength="30" minlength="3">
      <mat-error *ngIf="addInvoiceF['name'].errors && addInvoiceF['name'].errors['required']">Name is required</mat-error>
    </mat-form-field>
    <mat-form-field>
      <mat-label>Count</mat-label>
      <input type="number"  formControlName="count" matInput [formControl]="item.countFormControl" maxlength="100" minlength="1">
    </mat-form-field>
    <mat-form-field >
      <mat-label>Price</mat-label>
      <input type="number" matInput formControlName="price"  [formControl]="item.priceFormControl" maxlength="1000000" minlength="1">
      <mat-error *ngIf="addInvoiceF['price'].errors && addInvoiceF['price'].errors['required']">Price is required</mat-error>
    </mat-form-field>
    <button mat-icon-button color="primary" class="delete" matTooltip="Remove item" (click)="deleteForm(item)">
      <mat-icon>delete</mat-icon>
    </button>
  </div>
  <div class="add-new">
    <button type="button" mat-icon-button color="primary" class="add" matTooltip="Add new item" (click)="addForm()">
      <mat-icon>add</mat-icon>
      Add new item
    </button>
  </div>
  <div class="add">
    <button mat-icon-button color="primary" class="myButton"id="add_data_button">
      Submit
    </button>
  </div>
</form>

` And in TypeScript:

 import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroupDirective, NgForm, Validators, FormBuilder, FormGroup } from '@angular/forms';
import { ErrorStateMatcher } from '@angular/material/core';
import { ViewChild, ElementRef } from '@angular/core';
import { PagesService } from '../pages.service';
import { Router } from '@angular/router';

@Component({
  selector: 'app-new-invoice',
  templateUrl: './new-invoice.component.html',
  styleUrls: ['./new-invoice.component.css']
})
export class NewInvoiceComponent implements OnInit {


  matcher = new ErrorStateMatcher();
  addInvoiceForm!: FormGroup;
  get addInvoiceF() { return this.addInvoiceForm.controls; }

  items: any[] = [
    { nameFormControl: new FormControl(), countFormControl: new FormControl(), priceFormControl: new FormControl() }
  ];

  formRows: any[] = [{ name: '', count: 1, price: '' }];

  constructor(
    private formBuilder: FormBuilder,
    private pagesService: PagesService,
    private router: Router
  ) {
    window.addEventListener('beforeunload', () => {
      for (let key in localStorage) {
        if (key.includes('formRows')) {
          localStorage.removeItem(key);
        }
      }
    });
  }


  ngOnInit(): void {
    this.addInvoiceForm = this.formBuilder.group({
      name: ['', Validators.required],
      count: [''],
      price: ['', Validators.required],
    });
  }

  addFormRow() {
    this.formRows.push({ name: '', count: 1, price: '' });
  }

  addForm() {
    this.items.push({ nameFormControl: new FormControl(), priceFormControl: new FormControl() });
  }

  deleteForm(item: any) {
    const index = this.items.indexOf(item);
    if (index !== -1) {
      this.items.splice(index, 1);
    }
  }

  addData() {
    if (this.addInvoiceForm.invalid) {
      return;
    }
    this.formRows = this.items.map(item => ({
      name: item.nameFormControl.value || '',
      count: item.countFormControl ? item.countFormControl.value : '',
      price: item.priceFormControl.value || '' 
    }));
    this.pagesService.setFormData(this.formRows);
    console.log(this.formRows);
    this.router.navigate(['/preview-invoice']);
  }
}

I attempted using an "else" statement as well:

     addData() {
    if (this.addInvoiceForm.invalid) {
      return;
    } else {
    this.formRows = this.items.map(item => ({
      name: item.nameFormControl.value || '',
      count: item.countFormControl ? item.countFormControl.value : '',
      price: item.priceFormControl.value || '' 
    }));
    this.pagesService.setFormData(this.formRows);
    console.log(this.formRows);
    this.router.navigate(['/preview-invoice']);
  }}
}

Yet, the same issue persists. Therefore, the problem does not lie with the service or data but rather with the "this.addInvoiceForm.invalid" condition, and the reason behind it remains uncertain.

Answer №1

Make sure to call the updateValueAndValidity() method prior to verifying the validity of the form.

addData() {
      this.addInvoiceForm?.updateValueAndValidity();
      this.addInvoiceForm?.get('name')?.updateValueAndValidity();
      this.addInvoiceForm?.get('price')?.updateValueAndValidity();
      if (this.addInvoiceForm.invalid) {
          return;
      }
.....

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

Filtering data on objects in Angular can be achieved by utilizing the built-in

Retrieving data from the backend using this function: private fetchData(): void { this.dataService.fetchData().pipe( tap((response: any) => { this.persons = response.results; this.familyMembersTrue = this.persons.filter(x =&g ...

Encountering a NgForm provider error in Angular 4.4.6 development mode

UPDATE: Identifying the root of the issue has led me to search for a suitable solution. NOTE: This complication is specific to development mode (not production, and not utilizing AOT). The "Update" resolution I am implementing can be found here. In an a ...

Issue: Unable to locate the module 'nexmo' & error TS2307: 'nexmo' module not found

Currently, I am utilizing the powerful NestJs Framework alongside typescript. My task involves incorporating two-factor authentication (SMS) using the Nexmo node library. You can find further information on their website: During the development phase, ev ...

Tips for retrieving the value of a dynamically generated input field in Angular

After creating an empty hash map of a 'question' object in Angular based on the number of questions provided on the previous page, I am now displaying the 'question' objects from the hash map when the page loads. My goal is to retrieve ...

AngularJS 1.5: Observing scope changes with $watch in the link function fails to register updates when the model is modified

Greetings everyone! I'm currently working on a web application using typescript and angular 1.5; One of the components I've built is a directive that aims to monitor whether a user is logged in or not, and accordingly show or hide certain eleme ...

Changing the font family for a single element in Next.js

One unique aspect of my project is its global font, however there is one element that randomly pulls font families from a hosted URL. For example: https://*****.com/file/fonts/Parnian.ttf My page operates as a client-side rendered application (CSR). So, ...

What is causing these TypeScript type assertions to go unnoticed?

While reviewing type assertions, I noticed something interesting about the last three variable assignments - they don't produce errors. It's perplexing because I thought I was trying to change 'helo' into 'hello', which should ...

Error in JSON parsing: Unexpected token 'u' at the beginning of the input in Angular2

I attempted to create a server using dummy data. Below is the System.js Config I have implemented (given that my routing is slightly different, this setup has been working well so far) System.config({ // baseURL to node_modules b ...

Issues with KeyboardEvent keydown in Angular 2 causing malfunction

I need help with triggering a keydown event that changes the pressed key to a comma. If a non-numeric value is entered, it should simulate the comma and write it in the textbox. However, after the second call, the comma is not displayed. Any suggestions on ...

Why is my Angular promise unexpectedly landing in the error callback?

I am facing an issue with my Angular + Typescript client. I have developed a PHP API and need to send a post request to it. Upon receiving the request, the server fills the response body with the correct data (verified through server debugging). However, w ...

Angular now displays an unsupported Internet Explorer version message instead of showing a white screen

I am responsible for developing new features and maintaining an Angular application (version 8.3.4). Initially, we wanted the application to be compatible with all versions of Internet Explorer, but that turned out to be impractical. While the application ...

The Typescript error message states that the type '{ onClick: () => void; }' cannot be assigned to the type 'IntrinsicAttributes'

I'm a beginner in Typescript and I'm encountering difficulties comprehending why my code isn't functioning properly. My goal is to create a carousel image gallery using React and Typescript. However, I'm facing issues when attempting t ...

Creating a dynamic method to set data for a stacked bar chart in chart.js

In the following code snippet, you can see how my stacked bar chart is rendered using Angular: <canvas baseChart [datasets]="barChartData" [labels]="barChartLabels" [options]="barChartOptions" [legend]="barChartLegend" [chartType]=" ...

TypeScript: When using an API, it consistently returns an empty object with the type { [key: string]: any }

Every time I try to fetch data from the API, it always comes back empty. See example code snippet below: interface DataStore { [key: string]: any, } static GetData = async (req: Request, res: Response): Promise<Response> => { let obj: Dat ...

Camera Capacitor designed to eliminate popup notifications

I am utilizing Angular along with the camera plugin in Capacitor to locally save images on both desktop and tablets. I aim to utilize the CameraSource to directly access the camera or open the gallery for files without displaying a prompt. This is how my ...

NestJS Logger: Issue setting logger types in main.ts

When attempting to specify logger types in main.ts as illustrated in the official documentation: const app = await NestFactory.create(ApplicationModule, { logger: ['error', 'warn'], }); await app.listen(3000); I am encountering an i ...

Encountering an "Offset exceeds DataView bounds" error while trying to load an .STL model in Angular 9

I've been trying to incorporate a 3D model view into my website using the stl-model-viewer provided at: https://www.npmjs.com/package/angular-stl-model-viewer Despite following the installation steps, it seems that I'm unable to get it to work. T ...

Enhance the Component Props definition of TypeScript 2.5.2 by creating a separate definition file for it

I recently downloaded a NPM package known as react-bootstrap-table along with its type definitions. Here is the link to react-bootstrap-table on NPM And here is the link to the type definitions However, I encountered an issue where the types are outdate ...

How can a service be injected in NestJs based on its interface?

I have a module named payment.module.ts with the following setup: @Module({ controllers: [PaymentController], }) export class PaymentModule {} In my payment.service.ts file, I want to utilize a service that adheres to an interface. Here is an example ...

Incorporating lodash in a project with TypeScript and jspm

I seem to be missing something in my setup and would appreciate any assistance. I am working with TypeScript 2 + JSPM. I have tried various configurations in tsconfig using typeRoots and types (including adding the version number in the type name). Despite ...