What is the best way to customize a div depending on the validation status of all reactive form fields within it?

I am facing a challenge with a rather complex form that contains multiple fields. Some of these fields are used to create logical blocks, and I would like to emphasize the surrounding div if any of these included fields are invalid. Can you suggest the best approach to accomplish this?

Currently, I have been attempting the following implementation, but I seem to be stuck at a certain point

import { Component } from '@angular/core';
import {FormBuilder, Validators} from "@angular/forms";

@Component({
  selector: 'app-root',
  template: `
    <form [formGroup]="form">
      <input formControlName="name">
      <div class="div-address" [class.div-error]="DivHasError(divAddress)" #divAddress>
        <div class="div-text">Address</div>
        <input formControlName="addressType">
        <div formGroupName="address">
          <div>
            <input formControlName="street">
          </div>
          <div>
            <input formControlName="city">
          </div>
        </div>
      </div>
    </form>
  `,
  styles: [
    `
      input.ng-invalid {border-color: red;}
      .div-error .div-text {color: red;}
    `
  ]

})
export class AppComponent {
  protected form = this.fb.group({
    name: ['', Validators.required],
    addressType: ['office', Validators.required],
    address: this.fb.group({
      street: ['', Validators.required],
      city: ['', Validators.required],
    })
  });
  constructor(private fb: FormBuilder) {
  }

  DivHasError(divElement: HTMLDivElement): boolean {
    //TODO: Implement a more generic way to determine if any of the included fields are valid
    // Return True if any included field is invalid, otherwise False
    ???
  }
}

I am seeking a generic solution that does not involve manually listing all the fields in the "DivHasError" method. What would be the most efficient approach to achieve this?

Answer №1

Why not simplify things?

Anytime a field is invalid, Angular will automatically add the ng-invalid class to it. So all you need to do is list them in your CSS file.

For more information on form validation in Angular, check out this resource and learn about Control status CSS classes.

Answer №2

After carefully analyzing the issue, I came up with a simple solution. Here's a handy function that can verify if any fields within the div contain invalid data:

function CheckFormControls(form: FormGroup, elements:Element[], path: string[], controls: AbstractControl[]) {
  for (let child of elements) {
    const formGroupName = child.getAttribute('formGroupName');
    const formControlName = child.getAttribute('formControlName');
    const fieldPath = formGroupName ? [...path, formGroupName] : path;
    if (formControlName) {
      const field = form.get([...fieldPath, formControlName]);
      if (field) {
        controls.push(field)
      }
    }
    if (child.children.length > 0) {
      CheckFormControls(form, Array.from(child.children), fieldPath, controls);
    }
  }
}

export function ValidateDiv(formGroup: FormGroup, div:HTMLDivElement): boolean {
  const controls: AbstractControl[] = [];
  CheckFormControls(formGroup, Array.from(div.children), [], controls);
  for (let control of controls) {
    if (!control.valid) {
      return true;
    }
  }
  return false;
}

As for the HTML part:

<div class="div-address" [class.div-error]="ValidateDiv(form, divAddress)" #divAddress>

I do have some concerns about performance given the complexity of the validation logic, but at first glance, it seems acceptable.

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

How can you turn a SWFObject into a clickable link?

Is there a way to create a clickable link using a .swf flash file with swfObject? I want the entire video to be clickable, but I'm struggling to figure out how to do it. If you take a look at this example here: , you'll see that they were able ...

The carousel top position in Bootstrap 4 is not functioning properly

I am struggling to get the teal rectangle to move to the top of the carousel. I have set my carousel to have a position relative and my teal rectangle to have a position absolute with top="0", but it doesn't seem to be working properly. Instead of mov ...

Exploring the potential of Angular2's WebSocket service by efficiently accessing the parent component

I need some assistance with implementing WebSockets in my angular2 application. However, I've encountered a minor issue that I can't seem to solve. Here's what I have so far: I've created a service that has a method for creating a WebS ...

Transform the image background on mouse hover using CSS

On my php page, I am dynamically visualizing thumbnails. To ensure that they are all the same size, I use the following method: <a class="zoom" href="..."> <img src="thumb/default.png" width="130" style="background-image:url(thumb/<?php echo $ ...

Conceal navigation button within react-material-ui-carousel

After successfully incorporating the React Material UI carousel, I found it to be quite simple. However, one thing that eluded me was how to hide the buttons and only display them on hover. I tried setting the props navButtonsAlwaysVisible to false, but it ...

``Stylishly Designed CSS Tabs inspired by Google Chrome's Modern

Utilizing Material UI Tabs in React to create curved tabs resembling those seen in Google Chrome. The design requires the parent element to have a bottom border that extends across the entire row, appearing on both the tabs and other content on the right. ...

Getting a JSON value and saving it to a variable in Angular 4

Here is the JSON structure: { "Semester": [ { "queueName": "Science", "totalCount": 300, "unassignedCount": 10, "subjectDetails": [ { "subjectName": "Chemistry", "sectionOne": 100, "secti ...

Encountering an issue where the Angular build is unable to locate the installed Font-Awesome node module

Every time I attempt to compile my project using ng build --prod, I encounter the following error: ERROR in ./src/styles.scss Module build failed: ModuleBuildError: Module build failed: Error: Can't resolve '~font-awesome/css/font-awesom ...

Applying CSS styling to PHP documents

I am a beginner, so please go easy on me. I am looking to style variables like $product_name, $author, and $details. I was thinking of styling the echos, but in this scenario, the only echo is: <?php // Establish connection with the MySQL database ...

What is the best way to hide the div when scrolling to the top?

Is there a way to hide the circle once it's scrolled to the top? Currently, I can scroll the circle to the top but it remains visible. Upon further exploration, I found that clicking on the circle scrolls it to the top and then on a second click, it f ...

Encountering difficulties with implementing and utilizing bootstrap in Symfony 5.3 with Encore plugin

While I am currently dealing with an older version of Symfony, I decided to create a new 5.3 Symfony application from scratch. However, I am facing difficulties when trying to integrate bootstrap into it. After consulting some documentation, I proceeded to ...

"Trouble with Bootstrap 4 menu: only one dropdown opens at a time

I am facing an issue where the text remains a link and the dropdown toggle works, but it is causing Dropdown-2 to open when I click on Dropdown-1. Only Dropdown-1 seems to be working properly. I can't seem to figure out why only Dropdown-1 opens no m ...

Centering an icon vertically and introducing animation upon hovering over an image

I'm having difficulty with vertically centering an icon that drops down on image hover, and I want to make its transition smoother. Currently, it's dropping down too abruptly and no matter what transition property I apply (ease, ease-out, etc.), ...

"Utilizing ng2 dragula allows for the seamless addition of new data to an element after it has been dropped, based on the

My experience with the ng2 Dragula library revealed some intriguing aspects. I noticed that when dragging an element from one container to another, the element would expand to showcase additional data features such as Droplists, HTML input forms, and more ...

When attempting to build a production version of an Angular Ionic Capacitor project, a TypeError occurred stating that it cannot read the property 'updateClassDeclaration'

A short while back, I didn't encounter this error, but after executing npx audit fix --force, I started getting this error when running npm run build in my Ionic capacitor project: Module build failed (from ./node_modules/@angular-devkit/build-angular ...

Is it possible for the ionic ionViewDidEnter to differentiate between pop and setRoot operations?

I am facing an issue with my ionic 3 page where I need to refresh the data on the page only if it is entered via a navCtrl.setRoot() and not when returned to from a navCtrl.pop(). I have been using ionViewDidEnter() to identify when the page is entered, bu ...

Exploring Angular's View Encapsulation with Third-Party Libraries

When I integrate an external component into my own, I face a challenge with styling due to Angular View Encapsulation. Any CSS I define in my component does not affect the external component used in my HTML template. To work around this issue, I have set e ...

Locate the class ID and refine the search results by another class

I am currently working on a task that involves extracting the first <li> element's id where it has the class name my_class, and checking if the <span> with the class Time contains a ":" using jquery. Below is the sample HTML structure: & ...

Conceal the scrollbar track while displaying the scrollbar thumb

Hey there! I'm looking to customize my scroll bar to have a hidden track like this. Everyone's got their own style, right? ::-webkit-scrollbar{ width: 15px; height: 40px; } ::-webkit-scrollbar-thumb{ background-color: #DBDBDB; borde ...

What is the best way to add a clickable link/button in Angular 8 that opens a webpage in a new tab?

I'm looking to create a website that opens in a new tab when a link or button is clicked. I'm unsure how to achieve this in Angular 8. ...