← Back to Ada
AgentAda

Skill · Version 1.0.0

Angular Reactive Forms

Implements typed form controls, cross-field validation and server feedback with a predictable submission lifecycle.

angular-reactive-forms

See how it helps

When is it useful?

Use when Angular forms contain repeatable sections, asynchronous checks or confusing disabled and pending states.

What does it help you do?

  • Chooses typed groups, arrays and records that match the actual field structure.
  • Places field and cross-field validators correctly and controls asynchronous request frequency.
  • Maps server errors to controls while preserving general errors and preventing duplicate saves.

Try asking this

Build an editable invoice form with line items, date-range validation and server errors attached to the relevant fields. Add and remove line items, then reject a date range on the server. The correct controls should show errors while totals and entered items remain intact.

Detailed documentation

Read the skill’s original instructions, examples and checks in their authored language.

Details…Show less

Reactive Forms

Build predictable, strictly typed Angular Reactive Forms with clear separation between field validation, cross-field rules and server validation feedback.

1. Typed Reactive Forms (FormGroup, NonNullableFormBuilder, FormArray)

  • Use typed FormBuilder / NonNullableFormBuilder (inject(NonNullableFormBuilder)) so form.getRawValue() and form.value carry exact TypeScript types (FormControl<string> vs FormControl<string | null>).
  • Remember that form.value omits disabled controls (Partial), whereas form.getRawValue() includes disabled controls with their full type.
  • For dynamic lists or repeatable field sets, use FormArray<FormGroup<...>>; for dynamic string keys with uniform control types, use FormRecord<FormControl<...>>.
  • When populating existing data into a form, choose patchValue (partial updates) vs reset(model) (which also resets dirty/touched states) deliberately, and pass { emitEvent: false } when hydrating initial data should not trigger valueChanges pipelines.

2. Sync, cross-field and async validation

  • Attach single-field validators (Validators.required, custom ValidatorFn) to the FormControl, and cross-field validators (date ranges, password confirmation, totals) to the parent FormGroup.
  • For async validators (AsyncValidatorFn), debounce or run on updateOn: 'blur' so every keystroke does not fire a network request, and handle errors gracefully inside the observable.
  • Show field errors only when appropriate (control.invalid && (control.touched || formSubmitted)), and call form.markAllAsTouched() when the user attempts to submit an invalid form.

3. Submission lifecycle and server validation errors

  • Prevent duplicate submissions by guarding on form.pending || isSubmitting (or using exhaustMap).
  • Map field-level server errors onto matching controls via control.setErrors({ server: message }) while preserving a form-level banner/alert for general or unmapped server errors.

Before you finish

  • Controls use strict types (NonNullableFormBuilder where reset should restore defaults rather than null).
  • disabled, touched, dirty and pending states are handled and reflected in the UI.
  • Field, cross-field and server validation errors display clearly without losing user input.

Included files 2

  • LICENSE.txt
  • SKILL.md