After creating a Reactive Form in Angular 16 and adding Bootstrap validation to it, I encountered an issue where normal built-in validators work fine but custom validators do not reflect properly. Even though the error is added to the errors
array, Bootstrap still shows the input element as valid.
In my bootstrap-form.component.html file, the code looks like this:
<div class="container">
<div class="row">
<div class="col">
<h2 class="text-center fs-3 semibold">
{{ loginForm.value | json }}
</h2>
<form class="needs-validation" [formGroup]="loginForm" novalidate>
<div class="mt-4">
<label for="username-input" class="form-label fs-4">
username
</label>
<input
type="text"
id="username-input"
placeholder="username"
class="form-control mt-2"
formControlName="username"
required
/>
<div
class="invalid-feedback"
*ngIf="
loginForm.controls['username'].hasError('required')
"
>
Username cannot be empty
</div>
</div>
<div class="mt-4">
<label for="password-input" class="form-label fs-4">
password
</label>
<input
type="password"
id="password-input"
placeholder="password"
class="form-control mt-2"
formControlName="password"
required
/>
<div
class="invalid-feedback"
*ngIf="
loginForm.controls['password'].hasError('required')
"
>
Password cannot be empty
</div>
<div
class="invalid-feedback"
*ngIf="
loginForm.controls['password'].errors?.['passwordInvalid']
"
>
Password must be at least 8 characters long
</div>
<h3 class="fs-6">
{{ loginForm.controls["password"].errors | json }}
</h3>
</div>
<div class="mt-4">
<button type="submit" class="btn btn-primary col-12">
Login
</button>
</div>
</form>
</div>
</div>
</div>
In the bootstrap-form.component.ts file, here is the relevant code snippet:
import { Component, OnInit } from '@angular/core';
import {
AbstractControl,
FormBuilder,
FormControl,
FormGroup,
Validators,
} from '@angular/forms';
@Component({
selector: 'app-bootstrap-form',
templateUrl: './bootstrap-form.component.html',
styleUrls: ['./bootstrap-form.component.css'],
})
export class BootstrapFormComponent implements OnInit {
loginForm: FormGroup;
constructor(private formBuilderService: FormBuilder) {
this.loginForm = this.formBuilderService.group({
username: ['', [Validators.required]],
password: ['', [Validators.required, validatePassword]],
phoneNumber: ['', [Validators.required]],
});
}
ngOnInit(): void {
let form = document.querySelector('form') as HTMLFormElement;
form.addEventListener('submit', (submitEvent: SubmitEvent) => {
if (!form.checkValidity()) {
submitEvent.preventDefault();
submitEvent.stopPropagation();
}
form.classList.add('was-validated');
});
}
}
export function validatePassword(
formControl: AbstractControl
): { [key: string]: any } | null {
if (formControl.value && formControl.value.length < 8) {
return { passwordInvalid: true };
}
return null;
}
https://i.sstatic.net/n8BGS.png https://i.sstatic.net/nb84d.png
Upon reviewing the attached screenshots, it is evident that the errors
array contains an error, yet Bootstrap displays the field as valid. This discrepancy has left me puzzled, and I am unsure of what steps to take next in troubleshooting this issue.
If anyone can offer insight into what might be causing this unexpected behavior, I would greatly appreciate it.