Adding an asterisk to mark a required field in Angular reactive form inputs is a simple task that can be accomplished with just a

Currently, I am in the process of developing an application that utilizes a reactive dynamic angular form. The fields for this form are retrieved from an API request and generated dynamically.

I have encountered the need to include a 'required field' asterisk (*) next to the form inputs that are mandatory. Can anyone provide guidance on how to achieve this?

Below is an example of what my form fields currently look like:

<ng-container *ngIf="input1.type=='string'" [hidden]="False">
 <div>
  <mat-form-field>
   <input matInput   [formControlName]="input1.field_name"  type="text"  placeholder="{{input1.title}}">
  </mat-form-field>   
 </div>
</ng-container>

Answer №1

Here is my solution using a newly generated Directive:

  ng generate directive directive/mark-asterisk

This snippet shows the complete code of the directive:

import {Directive, ElementRef, Input, OnInit} from '@angular/core';
import {FormGroup} from '@angular/forms';

@Directive({
  selector: '[appMarkAsterisk]'
})
export class MarkAsteriskDirective implements OnInit {
  @Input() formGroup: FormGroup;
  @Input() controlName: string;

  constructor(private elementRef: ElementRef) {
  }

  ngOnInit(): void {
    const isRequired = this.formGroup.controls[this.controlName]?.errors?.required;
    if (isRequired) {
      this.elementRef.nativeElement.innerHTML = '*';
    }else{
      this.elementRef.nativeElement.innerHTML = '';
    }
  }
}

To use this directive in your HTML form, include it like so:

<label>Company name: <span appMarkAsterisk [formGroup]="formGroup" [controlName]="'companyName'"></span></label>

Answer №2

Once Angular v13 is officially launched, this issue should be resolved. Check out the progress at this GitHub link

Answer №3

HTML

<span *ngIf="input1?.required">*</span>

.TS

If you need to make an input required based on certain conditions, refer to this source

Answer №4

To indicate required validation in a reactive form field, you can bind the required attribute to the input element and display an asterisk (*) when validation is triggered.

<input formControlName="name" [required]="formGroup.get('name').errors !== null && formGroup.get('name').errors.required">

Answer №5

Implementing a directive or using the required attribute on the element may serve as a quick fix for now, but rest assured that a permanent solution is in the works and will be implemented shortly!

The issue at hand can be found here: https://github.com/angular/components/issues/2574?_pjax=%23js-repo-pjax-container.

Various temporary workarounds have been proposed in the comments section. I will make sure to update this response once the bug has been properly addressed.

Answer №6

Although there isn't a clear-cut solution readily available, I do have a suggestion to offer:

@Component({
  selector: "app-root",
  template: `
    <form [formGroup]="formGroup">
      <mat-form-field>
        <input
          matInput
          type="text"
          [required]="isRequired(input1.field_name)"
          [placeholder]="input1.title"
          [formControlName]="input1.field_name"
        />
      </mat-form-field>
    </form>
  `,
})
export class AppComponent {
  readonly formGroup = new FormGroup({
    name: new FormControl("", Validators.required),
  });

  readonly input1 = { field_name: "name", title: "Name", type: "string" };

  isRequired(name: string): boolean {
    return this.formGroup.get(name)?.hasValidator(Validators.required) ?? false;
  }
}

Answer №7

It appears that the validators are executed from the typescript file, however, you can easily add an asterisk by modifying the html file.

<input matInput   [formControlName]="input1.field_name"  type="text"  [placeholder]="{{input1.title}}" required>

Answer №8

To start, develop a directive that will insert an asterisk without interfering with input attributes:

import { AfterContentChecked, Directive, Optional } from "@angular/core";
import { AbstractControl } from "@angular/forms";
import { MatFormField, MatInput, MatSelect } from "@angular/material";

/**
 * For Input/Select elements within FormField, apply the Validator.required from reactive forms if the [required] attribute is absent in the template
 */
@Directive({
  selector: 'mat-form-field:has(input:not([required])), mat-form-field:has(mat-select:not([required]))'
})
export class ReactiveAsteriskDirective implements AfterContentChecked {
  constructor(@Optional() private matFormField: MatFormField) { }

  ngAfterContentChecked() {
    if (this.matFormField) {
      const ctrl = this.matFormField._control;
      if (ctrl instanceof MatInput || ctrl instanceof MatSelect)
        if (ctrl.ngControl)
          if (ctrl.ngControl.control)
            if (ctrl.ngControl.control.validator)
              if (ctrl.ngControl.control.validator({} as AbstractControl))
                ctrl.required = ctrl.ngControl.control.validator({} as AbstractControl).required;
    }
  }
}

Next, you can modify the appearance of the asterisk by making it red to signify a mandatory input field. Simply add the following CSS to your component:

:host ::ng-deep .mat-placeholder-required {
  color: red;
}

Answer №9

An attribute directive can be created to automatically add the required attribute to an element based on the presence of the Validators.required validator in the corresponding form control:

import { Directive, ElementRef, OnInit } from '@angular/core';
import { FormControlName, NgControl, Validators } from '@angular/forms';

@Directive({
  selector: '[formControl], [formControlName]',
  standalone: true,
})
export class FormControlRequiredAttributeDirective implements OnInit {
  constructor(private elementRef: ElementRef, private ngControl: NgControl) {}

  ngOnInit(): void {
    if (
      (this.ngControl instanceof FormControlName || this.ngControl instanceof FormControlDirective) && 
      this.ngControl.control.hasValidator(Validators.required)
    ) {
      this.elementRef.nativeElement.required = 'true';
    }
  }
}

Simply importing and using this directive in your component will apply the functionality:

@Component({
  imports: [ReactiveFormsModule, FormControlRequiredAttributeDirective],
  // ...
})
class LoginFormComponent {
  formGroup: FormGroup = new FormGroup({
    email: new FormControl('', Validators.required),
  });
}
<form [formGroup]="formGroup">
  <label>
    <span>Email</span>
    <input type="email" formControlName="email" />
  </label>
</form>

By following this approach, you ensure that validators are the sole source of truth, reducing repetition in your code.

Answer №10

After setting the required bit in the FormGroup, I found that there was no need to set it in the HTML as well. While examining the CSS class list, I noticed that the class ng-star-inserted had been added, but the star itself was missing. To rectify this, I included the following CSS:

mat-label.ng-star-inserted::after {
    content: " *";
}

Upon further investigation using template forms in Angular with the [required]="condition" syntax, I observed that a

<span class="ng-star-inserted"> *</span>
element is appended after the label.

Despite initial doubts, applying this CSS solution proved successful for me. Interestingly, upon testing, I discovered that all elements - whether inputs, labels, divs, dialogs, or icons - were now marked with .ng-star-inserted. Reinstating the CSS brought stars everywhere, much to my surprise.

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

Angular Date of Birth Verification

I'm new to Angular and struggling with date handling. I have a form that includes fields for the user's name and their date of birth. Before submitting the form, I need to validate that the person is over 18 years old and display an error messag ...

Displaying the focus icon on the active tab using Angular Material

I am currently utilizing Angular material to dynamically generate tabs in my HTML code. I'm trying to display a drop arrow icon on the active or selected tabs, but I am facing some challenges with the implementation. Below is the code snippet I have ...

Tips for exporting an array of dynamic JSON objects to CSV using Angular

I am facing a challenge in exporting an array of JSON objects to CSV as the number of key-value pairs can vary, leading to additional columns in some objects. Currently, I am using the Angular2CSV package for export functionality, but it requires all colum ...

The <h:outputStylesheet> tag fails to display any content on the HTML page

I am having trouble getting my CSS sheet to load while using JSF2 and PrimeFaces. The CSS file is located at WebContent/resources/css/style.css Here is the xhtml code: <h:head></h:head> <h:body> <h:outputStylesheet name="css/styles. ...

Tips on formatting text as bold or italic when tweeting from my website to our Twitter account

Currently, I am utilizing the Twitter OAuth library in conjunction with PHP to publish a tweet from my website directly to my Twitter account. My main objective is to highlight some text while posting, however, I have not been successful in identifying t ...

After verifying the variable is an Array type, it is ideal to utilize the .forEach()

Within my generic functional component, I have the following code snippet: if(Array.isArray(entry[key as keyof T]) { entry[key as keyof T].forEach((item: T) => { ... }); } The variable key is a string that dynamically changes. However, when attempt ...

Can someone please explain the purpose of row-sm and row-cols-sm-n (where n<12)? I've come across the col-sm-n (where n<12) but I'm unsure about how row-sm is used

From my understanding, when using col-sm-n in Bootstrap, the columns in a row will stack on top of each other when the device screen width is less than the specified size for sm. But what about row-sm? Does it function similarly to col-sm? And what exactly ...

Return the previous value if the filter function returns false in RxJs

In an attempt to optimize performance and reduce unnecessary requests to the server, this code checks if values exist in the store before making additional requests. While the overall logic functions correctly, there is an issue where if the filter returns ...

Organizing the website's files and extensions

Transitioning from programming desktop applications to websites can be overwhelming, especially when dealing with multiple languages and extensions like JavaScript, CSS, JSON, Bootstrap, Ajax, and PHP all at once. How do you effectively juggle these diff ...

What is the best way to bring a closing </div> tag closer to its opening <div> tag in React, Angular, or Vue

Introduction Experienced JavaScript developers may cringe at the sight of a lengthy 200-line function. Their goal is to break it down into smaller, more manageable functions, each around 20 lines long. The idea is for a function to fit on one screen witho ...

Angular 6 Universal does not pause for resolver completion

I recently completed the installation of Angular Universal start kit version 6 and designed my component within it. The main purpose of this component is to retrieve user information from an API upon loading and display it on the view. The issue I am faci ...

Debugging TypeScript on a Linux environment

Approximately one year ago, there was a discussion regarding this. I am curious to know the current situation in terms of coding and debugging TypeScript on Linux. The Atom TypeScript plugin appears promising, but I have not come across any information ab ...

Is there a way to easily toggle a Material Checkbox in Angular with just one click?

Issue with Checkbox Functionality: In a Material Dialog Component, I have implemented several Material Checkboxes to serve as column filters for a table: <h1 mat-dialog-title>Filter</h1> <div mat-dialog-content> <ng-container *ng ...

The issue of duplicate CSS arising during the compilation of SASS into a single CSS file with G

Just getting started with Stack Overflow and Gulp (using version 3.9.1). My goal is to compile all of my scss files into a single css file for my website. Here's what I have in my gulpfile so far: var gulp = require('gulp'); var sass = requ ...

The ngrx action is mysteriously invoked without being explicitly called within the effect

I've implemented an effect to load data and defined actions for load success and load failure. The effect is functioning correctly, but it seems to be calling both actions (success and failure) even though I have only returned load success. When I tri ...

Custom providers do not override Angular UrlResolver

In my Angular application, I am trying to implement a custom UrlResolver provider to incorporate cache breaking logic. I came across this question on Stack Overflow: . Unfortunately, it seems that overriding the default compiler UrlResolver using a provid ...

Make sure to load the <img> html tag before implementing js masonry for optimal

I am facing an issue with jQuery Masonry as it arranges my 'bricks' immediately without waiting for images to load in. Additionally, I need the images to be responsive so I cannot define their height and width like this: <img src="asas" heigh ...

What is the best way to retrieve the URL query parameters in a Node.js environment?

How can I retrieve URL query parameters in Node.js using TypeScript? Below is my attempted code: /** * My Server app */ import * as Http from "http"; import * as url from "url"; import { HttpServer } from "./HttpServer"; import { TaxCalculator } from ". ...

Styling the CSS tables with alternating row styles for rows 1 and 2, followed by a different style for rows 3 and 4. This pattern will repeat

I've been struggling to create a CSS table style using tr:nth-child to alternate row colors: Row 1 - Blue Row 2 - Blue Row 3 - White Row 4 - White ... and so on. I can't seem to get it right! Can anyone help me out with this? Appreciate an ...

Attempting to utilize Array Methods with an Array Union Type

Currently, I am in the process of refactoring an Angular application to enable strict typing. One issue I have encountered is using array methods with an array union type in our LookupService. When attempting to call const lookup = lookupConfig.find(l =&g ...