angularvalidationangular-formsangular-validationangular-template-form

Angular Template-Driven Form: Validate Password Field Only After User Interaction


I have a form:

<input
            type="password"
            id="password"
            name="password"
            ngModel
            #password="ngModel"
            placeholder="Input text"
            required
          />
          <span
            *ngIf="password.touched && password.invalid"
            id="passwordErrorMessage"
            class="text-danger"
            >Password is required.</span
          >
        </div>

this is a template-driven-form

The problem with validation now is that when the form is loaded- and the input is empty, it is red. The input should be red not when the form is loaded, but when the input was touched and still is empty. How to do it?

the whole code:

<h2 class="text-align-center">Login</h2>
<div class="app-plate">
  <form #loginForm="ngForm">
    <div class="login-form">
      <div>
        <div class="form__control">
          <label for="email">Email</label>
          <!--Use the name `email` for the form control.-->
          <input
            type="email"
            id="email"
            placeholder="Input text"
            name="email"
            emailValidator
            ngModel
            #email="ngModel"
            required
          />
          <span
            *ngIf="password.touched && password.invalid"
            id="emailErrorMessage"
            class="text-danger"
            >Email is required.</span
          >
        </div>
        <div class="form__control">
          <label for="password">Password</label>
          <!--Use the name `password` for the form control.-->
          <input
            type="password"
            id="password"
            name="password"
            ngModel
            #password="ngModel"
            placeholder="Input text"
            required
          />
          <span
            *ngIf="password.touched && password.invalid"
            id="passwordErrorMessage"
            class="text-danger"
            >Password is required.</span
          >
        </div>
      </div>
      <div>
        <div class="form__action">
          <app-button button_text="Login"></app-button>
        </div>
        <div class="form__text">
          If you don't have an account you may <strong>Registration</strong>
        </div>
      </div>
    </div>
  </form>
</div>

Solution

  • You need to change your CSS, to also validate ng-touched along with ng-invalid, this will set the red border only when the input is touched.

    global_styles.scss

    input.ng-invalid.ng-touched {
      border: 1px solid red;
    }
    

    Full Code:

    import { Component } from '@angular/core';
    import { bootstrapApplication } from '@angular/platform-browser';
    import { FormsModule } from '@angular/forms';
    import { CommonModule } from '@angular/common';
    
    @Component({
      selector: 'app-root',
      imports: [FormsModule, CommonModule],
      standalone: true,
      styles: [
        `
      `,
      ],
      template: `
      <div>
        <input
          type="password"
          id="password"
          name="password"
          ngModel
          #password="ngModel"
          placeholder="Input text"
          required
        />
        <span
          *ngIf="password.touched && password.invalid"
          id="passwordErrorMessage"
          class="text-danger"
          >Password is required.</span
        >
      </div>
      `,
    })
    export class App {
      name = 'Angular';
    }
    
    bootstrapApplication(App);
    

    Stackblitz Demo