Skip to content

useControlStatus

Returns the validation status of an AbstractControl as a signal. The signal updates reactively whenever the control's status changes. Works with FormControl, FormGroup, and FormArray.

Usage

typescript
import { useControlStatus } from 'ng-reactive-utils';

@Component({
  template: `
    <input [formControl]="usernameControl" placeholder="Username" />

    <span [class]="'status-' + controlStatus().toLowerCase()">
      {{ controlStatus() }}
    </span>

    @switch (controlStatus()) {
      @case ('VALID') {
        <span class="success">Username is available</span>
      }
      @case ('INVALID') {
        <span class="error">Username is invalid</span>
      }
      @case ('PENDING') {
        <span class="loading">Checking availability...</span>
      }
      @case ('DISABLED') {
        <span class="info">Username cannot be changed</span>
      }
    }
  `,
  styles: `
    .status-valid {
      color: green;
    }
    .status-invalid {
      color: red;
    }
    .status-pending {
      color: orange;
    }
    .status-disabled {
      color: gray;
    }
  `,
})
class UsernameFieldComponent {
  usernameControl = new FormControl(
    '',
    [Validators.required, Validators.minLength(3)],
    [this.usernameAvailabilityValidator()],
  );

  controlStatus = useControlStatus(this.usernameControl);
}

Parameters

ParameterTypeDefaultDescription
controlAbstractControlrequiredThe control to get status from

Returns

Signal<FormControlStatus> - A readonly signal containing the control status

Status Values

StatusDescription
VALIDControl passes all validation
INVALIDControl has validation errors
PENDINGControl has pending async validators
DISABLEDControl is disabled

Notes

  • Works with FormControl, FormGroup, and FormArray
  • Uses toSignal with control.statusChanges observable
  • Useful for conditional rendering based on control state
  • Status changes trigger when value changes, validators run, or control is disabled/enabled

Source

ts
import { Signal } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { AbstractControl, FormControlStatus } from '@angular/forms';

/**
 * Returns the validation status of an AbstractControl as a signal.
 * The signal updates reactively whenever the control's status changes.
 * Works with FormControl, FormGroup, and FormArray.
 *
 * Status values:
 * - 'VALID': The control is valid
 * - 'INVALID': The control is invalid
 * - 'PENDING': The control has pending async validators
 * - 'DISABLED': The control is disabled
 *
 * @param control - The AbstractControl to get status from
 * @returns A signal containing the control status
 *
 * @example
 * ```typescript
 * @Component({
 *   template: `
 *     <input [formControl]="emailControl" />
 *     <span [class]="'status-' + controlStatus().toLowerCase()">
 *       Status: {{ controlStatus() }}
 *     </span>
 *   `
 * })
 * class MyComponent {
 *   emailControl = new FormControl('', Validators.required);
 *   controlStatus = useControlStatus(this.emailControl);
 * }
 * ```
 */
export const useControlStatus = (control: AbstractControl): Signal<FormControlStatus> => {
  return toSignal(control.statusChanges, {
    initialValue: control.status,
  }) as Signal<FormControlStatus>;
};

Released under the MIT License.