useControlErrors
Returns the validation errors of an AbstractControl as a signal. The signal updates reactively whenever the control's validation errors change. Works with FormControl, FormGroup, and FormArray.
Usage
typescript
import { useControlErrors } from 'ng-reactive-utils';
@Component({
template: `
<input [formControl]="emailControl" placeholder="Email" />
@if (errors()?.['required']) {
<span class="error">Email is required</span>
}
@if (errors()?.['email']) {
<span class="error">Please enter a valid email address</span>
}
@if (errors()?.['minlength']) {
<span class="error">
Email must be at least {{ errors()?.['minlength'].requiredLength }} characters
</span>
}
`,
})
class EmailFieldComponent {
emailControl = new FormControl('', [
Validators.required,
Validators.email,
Validators.minLength(5),
]);
errors = useControlErrors(this.emailControl);
}Advanced Usage
typescript
import { useControlErrors } from 'ng-reactive-utils';
@Component({
template: `
<input [formControl]="passwordControl" type="password" />
<ul class="validation-list">
@for (error of errorMessages(); track error) {
<li class="error">{{ error }}</li>
}
</ul>
`,
})
class PasswordFieldComponent {
passwordControl = new FormControl('', [
Validators.required,
Validators.minLength(8),
Validators.pattern(/[A-Z]/),
Validators.pattern(/[0-9]/),
]);
errors = useControlErrors(this.passwordControl);
errorMessages = computed(() => {
const errors = this.errors();
if (!errors) return [];
const messages: string[] = [];
if (errors['required']) messages.push('Password is required');
if (errors['minlength']) messages.push('Must be at least 8 characters');
if (errors['pattern']) messages.push('Must contain uppercase and numbers');
return messages;
});
}Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
control | AbstractControl | required | The control to get errors from |
Returns
Signal<ValidationErrors | null> - A readonly signal containing the validation errors or null if no errors
Common Error Types
| Error | Description |
|---|---|
required | Value is empty |
email | Value is not a valid email |
minlength | Value is shorter than required |
maxlength | Value is longer than allowed |
pattern | Value doesn't match the pattern |
min | Numeric value is below minimum |
max | Numeric value is above maximum |
Notes
- Works with FormControl, FormGroup, and FormArray
- Uses
toSignalwithcontrol.statusChangesobservable - Returns
nullwhen the control has no validation errors - Error object keys correspond to validator names
Source
ts
import { Signal } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { AbstractControl, ValidationErrors } from '@angular/forms';
import { map } from 'rxjs';
/**
* Returns the validation errors of an AbstractControl as a signal.
* The signal updates reactively whenever the control's validation errors change.
* Works with FormControl, FormGroup, and FormArray.
*
* @param control - The AbstractControl to get errors from
* @returns A signal containing the validation errors or null if no errors
*
* @example
* ```typescript
* @Component({
* template: `
* <input [formControl]="emailControl" />
* @if (errors()?.['required']) {
* <span>Email is required</span>
* }
* @if (errors()?.['email']) {
* <span>Please enter a valid email</span>
* }
* `
* })
* class MyComponent {
* emailControl = new FormControl('', [Validators.required, Validators.email]);
* errors = useControlErrors(this.emailControl);
* }
* ```
*/
export const useControlErrors = (control: AbstractControl): Signal<ValidationErrors | null> => {
return toSignal(control.statusChanges.pipe(map(() => control.errors)), {
initialValue: control.errors,
}) as Signal<ValidationErrors | null>;
};