Skip to content

useControlPending

Returns whether an AbstractControl has pending async validators as a signal. The signal updates reactively whenever the control's pending state changes. Works with FormControl, FormGroup, and FormArray.

Usage

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

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

    @if (isPending()) {
      <span class="loading-spinner">Checking availability...</span>
    }
  `,
})
class UsernameFieldComponent {
  usernameControl = new FormControl('', [], [asyncUsernameValidator]);
  isPending = useControlPending(this.usernameControl);
}

Advanced Usage

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

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

    @if (isPending()) {
      <div class="validation-status">
        <span class="spinner"></span>
        Validating email...
      </div>
    } @else if (emailControl.valid) {
      <div class="validation-status success">Email is available</div>
    }

    <button [disabled]="isPending() || emailControl.invalid">Continue</button>
  `,
})
class EmailVerificationComponent {
  emailControl = new FormControl('', [Validators.email], [asyncEmailValidator]);
  isPending = useControlPending(this.emailControl);
}

Parameters

ParameterTypeDefaultDescription
controlAbstractControlrequiredThe control to check pending state for

Returns

Signal<boolean> - A readonly signal containing the pending state (true if async validators are running)

Notes

  • Works with FormControl, FormGroup, and FormArray
  • Uses toSignal with control.statusChanges observable
  • Returns true when the control has pending async validators
  • Returns false when all validators have completed
  • Useful for showing loading indicators during async validation

Source

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

/**
 * Returns whether an AbstractControl has pending async validators as a signal.
 * The signal updates reactively whenever the control's pending state changes.
 * Works with FormControl, FormGroup, and FormArray.
 *
 * @param control - The AbstractControl to check pending state for
 * @returns A signal containing the pending state (true if async validators are running)
 *
 * @example
 * ```typescript
 * @Component({
 *   template: `
 *     <input [formControl]="usernameControl" />
 *     @if (isPending()) {
 *       <span>Checking availability...</span>
 *     }
 *   `
 * })
 * class MyComponent {
 *   usernameControl = new FormControl('', [], [asyncUsernameValidator]);
 *   isPending = useControlPending(this.usernameControl);
 * }
 * ```
 */
export const useControlPending = (control: AbstractControl): Signal<boolean> => {
  return toSignal(control.statusChanges.pipe(map(() => control.pending)), {
    initialValue: control.pending,
  }) as Signal<boolean>;
};

Released under the MIT License.