Why class is not applying on input element if it's invalid in Template driven form Angular 4?
Asked Answered
B

7

6

I used a template driven form for my login page. I want a red border on input elements if they are invalid or have any errors but the class borderRed is not being added on an input element when the input is blank or invalid.

<form (ngSubmit)="f.form.valid && signin()" #f="ngForm" class="m-login__form m-form" action="">
  <ng-template #alertSignin></ng-template>

  <div class="form-group form-md-line-input form-md-floating-label">
    <label>
      Email <span class="text-danger">*</span>
    </label>
    <input [class.borderRed]="email.invalid" class="form-control m-input" type="text" required="required" name="email" [(ngModel)]="model.email" #email="ngModel" autocomplete="off">
  </div>

  <div class="form-group form-md-line-input form-md-floating-label">
    <label [pTooltip]="attachementTooltipmsg" tooltipPosition="top" for="form_control_1">
      Password <span class="text-danger">*</span>
    </label>
    <input [class.borderRed]="password.invalid" class="form-control m-input" required="" name="password" type="password" [(ngModel)]="model.password" #password="ngModel">
  </div>

  <div class="m-login__form-action">
    <button [disabled]="loading" [ngClass]="{'m-loader m-loader--right m-loader--light': loading}" id="m_login_signin_submit" class="btn btn-focus m-btn m-btn--pill m-btn--custom m-btn--air">
      Sign In
    </button>
  </div>
</form>
Bustup answered 27/4, 2018 at 12:8 Comment(3)
Can you provide a small repro with stackblitz?Barstow
in your password input why is required field like required=""Rydder
try to console log email.invalid when it should trigger a change.Knudsen
C
3

Use this

   <input [class.borderRed]="email.touched && !email.valid" class="form-control m-input" type="email" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$" required name="email" [(ngModel)]="model.email" #email="ngModel" autocomplete="off">

Check out StackBiltz

Edited code

Cordovan answered 3/5, 2018 at 8:24 Comment(0)
P
1

Angular adds some css classes when an input is valid or not. You can override the css to make it look as you want. With this approach you don't have to do [class.borderRed]=... on every input. https://angular.io/guide/forms

.ng-valid[required], .ng-valid.required  {
  border: 1px solid green;
}

.ng-invalid:not(form)  {
  border: 1px solid red;
}
Poverty answered 3/5, 2018 at 8:58 Comment(0)
T
0

This should work

<input [ngClass]="{'borderRed':email.invalid}" class="form-control m-input" type="text" required="required" name="email" [(ngModel)]="model.email" #email="ngModel" autocomplete="off">
Tape answered 1/5, 2018 at 15:51 Comment(2)
Actually I got both methods to work - did you define border red? See this: angular-cic9xb.stackblitz.ioTape
stackblitz.com/edit/angular-m6r5tt - ignore the other link this has the edit so you can see it workingTape
D
0

For email validation add the email directive for example <input type="email" name="email" ngModel email>

Or you can use the pattern attribute, example :

<div class="form-group">
              <label for="inputEmail">Email</label>
              <input type="text"
                [ngModel] = "user.email" name="email"
                #email="ngModel" id="inputEmail"
                placeholder="Email"
                pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$"
                required>
            </div>

<!-- This is the error section -->

<div *ngIf="email.invalid && (email.dirty || email.touched)"
    class="alert alert-danger">
    <div *ngIf = "email.errors?.required">
        Email field can't be blank
    </div>
    <div *ngIf = "email.errors?.pattern && email.touched">
        The email id doesn't seem right
    </div>
 </div>

Also better mark the fields required just by adding required. For password input you can use a validator like this minlength ="8".

Generally you have to specify the validations rules. In reactive forms you would specify that in the component class for example :

this.myForm = this.f.group({ name: ['', Validators.required ], });

Dykstra answered 1/5, 2018 at 16:13 Comment(0)
S
0

You can do this. this works for me:-

<div class="form-group" [class.has-error]="fullnameControl.invalid && (fullnameControl.dirty || fullnameControl.touched)" 
        [class.has-success]="fullnameControl.valid">
            <label class="control-label">Full Name Field </label>
            <input 
                type="text" 
                required
                class="form-control" 
                name="fullname" 
                id="fullname" [(ngModel)]="fullname"
                #fullnameControl="ngModel"

            />
            <span class="help-block" 
               *ngIf="fullnameControl.invalid && (fullnameControl.dirty 
              || fullnameControl.touched)">Full Name is required. </span>
        </div>
Shaylyn answered 7/5, 2018 at 3:1 Comment(0)
C
0

Use ngClass for dynamically adding different classes. Example:

     <input class="form-control" id="firstName" name="firstName" type="text" placeholder="First Name" formControlName="firstName" [ngClass]="{
            'has-success': firstName.valid,
            'has-danger': (firstName.invalid && firstName.dirty) || (!isFormSubmitted && firstName.invalid)}">

If FirstName is invalid and dirty (user has actually touched this field), then add has-danger class.
If firstName is valid, then add has-success class.
Note: firstName is a form-control

Capacity answered 7/5, 2018 at 4:42 Comment(0)
G
0

To ensure that borderRed class is added to input elements when they are invalid or have any errors in an Angular template-driven form, you need to correctly bind to the ngModel directive and utilize the state properties it provides. Here’s a detailed approach to achieve this:

1 Ensure Correct Binding:

 -> Make sure your `ngModel` directives are correctly set up.

 -> Use the Angular-provided state properties `(invalid, dirty, touched)` to determine the validation state of the input fields.

2 Apply Conditional Classes: - Bind the borderRed class conditionally based on the validation state.

Here’s how you can modify your form to correctly apply the borderRed class when the inputs are invalid or have errors:

<form (ngSubmit)="f.form.valid && signin()" #f="ngForm" class="m-login__form m-form" action="">
  <ng-template #alertSignin></ng-template>

  <div class="form-group form-md-line-input form-md-floating-label">
    <label>
      Email <span class="text-danger">*</span>
    </label>
    <input [class.borderRed]="email.invalid && (email.dirty || email.touched)" 
           class="form-control m-input" 
           type="text" 
           required 
           name="email" 
           [(ngModel)]="model.email" 
           #email="ngModel" 
           autocomplete="off">
  </div>

  <div class="form-group form-md-line-input form-md-floating-label">
    <label [pTooltip]="attachementTooltipmsg" tooltipPosition="top" for="form_control_1">
      Password <span class="text-danger">*</span>
    </label>
    <input [class.borderRed]="password.invalid && (password.dirty || password.touched)" 
           class="form-control m-input" 
           required 
           name="password" 
           type="password" 
           [(ngModel)]="model.password" 
           #password="ngModel">
  </div>

  <div class="m-login__form-action">
    <button [disabled]="loading" [ngClass]="{'m-loader m-loader--right m-loader--light': loading}" id="m_login_signin_submit" class="btn btn-focus m-btn m-btn--pill m-btn--custom m-btn--air">
      Sign In
    </button>
  </div>
</form>
  1. Class Binding:
  • [class.borderRed]="email.invalid && (email.dirty || email.touched)": This binding ensures that the borderRed class is applied only when the email field is invalid and either dirty or touched.
  • [class.borderRed]="password.invalid && (password.dirty || password.touched)": Similarly, this binding ensures that the borderRed class is applied only when the password field is invalid and either dirty or touched.
  1. State Properties:
  • invalid: This property is true when the input field fails validation.
  • dirty: This property is true when the user has changed the value of the input field.
  • touched: This property is true when the user has focused on the input field and then blurred (focused out of) it.

Ensure you have the borderRed class defined in your SCSS file:

.borderRed {
  border: 1px solid red;
}
Gamber answered 17/5 at 18:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.