
Angular Forms
Implement production-grade Angular reactive forms with typed controls, validators, and FormArray patterns in agent-driven UI work.
Overview
angular-forms is an agent skill for the Build phase that implements Angular reactive form patterns—typed controls, validators, and FormArray—in frontend components.
Install
npx skills add https://github.com/analogjs/angular-skills --skill angular-formsWhat is this skill?
- 6 documented form topics: reactive forms, typed forms, FormBuilder, FormArray, custom validators, form state
- Production-stable ReactiveFormsModule patterns with touch-aware error display
- Typed FormControl and FormGroup examples for stricter TypeScript apps
- Dynamic lists via FormArray add/remove flows
- Custom sync and async validator patterns plus disabled-state handling
- 6 form pattern sections in the skill table of contents
Adoption & trust: 5.5k installs on skills.sh; 592 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your agent keeps generating brittle template-driven forms or untyped FormGroups that break under real validation and dynamic field requirements.
Who is it for?
Indie SaaS or mobile-web Angular apps where the agent is wiring login, onboarding, or data-entry screens.
Skip if: Non-Angular stacks, greenfield projects choosing another framework, or teams that only need HTML forms without Angular dependencies.
When should I use this skill?
User is building or refactoring Angular forms with reactive APIs, validators, or dynamic FormArray fields.
What do I get? / Deliverables
You get copy-paste-ready reactive form components with validators, dynamic arrays, and touch-aware errors that match Angular production conventions.
- Angular component code with reactive FormGroup/FormArray and validation UX
Recommended Skills
Journey fit
How it compares
Pattern reference skill for Angular Reactive Forms—not a generic HTML form generator or backend DTO validator.
Common Questions / FAQ
Who is angular-forms for?
Solo builders and small teams using Angular who want agents to follow consistent reactive form architecture in frontend code.
When should I use angular-forms?
Use it during Build/frontend whenever you add or refactor forms—login, settings, wizards, or dynamic lists needing Validators and FormArray.
Is angular-forms safe to install?
It is documentation-only with no network calls; still review the Security Audits panel on this Prism page before adding any third-party skill to your agent.
SKILL.md
READMESKILL.md - Angular Forms
# Angular Form Patterns ## Table of Contents - [Reactive Forms (Production-Stable)](#reactive-forms-production-stable) - [Typed Reactive Forms](#typed-reactive-forms) - [FormBuilder Patterns](#formbuilder-patterns) - [Dynamic Forms with FormArray](#dynamic-forms-with-formarray) - [Custom Validators](#custom-validators) - [Form State Management](#form-state-management) ## Reactive Forms (Production-Stable) For production applications requiring stability guarantees, use Reactive Forms: ```typescript import { Component, inject } from '@angular/core'; import { ReactiveFormsModule, FormBuilder, Validators } from '@angular/forms'; @Component({ selector: 'app-login', imports: [ReactiveFormsModule], template: ` <form [formGroup]="form" (ngSubmit)="onSubmit()"> <input formControlName="email" /> @if (form.controls.email.errors?.['required'] && form.controls.email.touched) { <span class="error">Email is required</span> } <input type="password" formControlName="password" /> <button type="submit" [disabled]="form.invalid">Login</button> </form> `, }) export class Login { private fb = inject(FormBuilder); form = this.fb.group({ email: ['', [Validators.required, Validators.email]], password: ['', [Validators.required, Validators.minLength(8)]], }); onSubmit() { if (this.form.valid) { console.log(this.form.value); } } } ``` ## Typed Reactive Forms ### Typed FormControl ```typescript import { FormControl } from '@angular/forms'; // Inferred type: FormControl<string | null> const name = new FormControl(''); // Non-nullable (no reset to null) const email = new FormControl('', { nonNullable: true }); // Type: FormControl<string> // With validators const username = new FormControl('', { nonNullable: true, validators: [Validators.required, Validators.minLength(3)], }); ``` ### Typed FormGroup ```typescript import { FormGroup, FormControl } from '@angular/forms'; interface UserForm { name: FormControl<string>; email: FormControl<string>; age: FormControl<number | null>; } const form = new FormGroup<UserForm>({ name: new FormControl('', { nonNullable: true }), email: new FormControl('', { nonNullable: true }), age: new FormControl<number | null>(null), }); // Typed value access const name: string = form.controls.name.value; ``` ### NonNullableFormBuilder ```typescript import { inject } from '@angular/core'; import { NonNullableFormBuilder } from '@angular/forms'; @Component({...}) export class Profile { private fb = inject(NonNullableFormBuilder); form = this.fb.group({ name: ['', Validators.required], // FormControl<string> email: ['', [Validators.required, Validators.email]], preferences: this.fb.group({ newsletter: [false], // FormControl<boolean> theme: ['light' as 'light' | 'dark'], // FormControl<'light' | 'dark'> }), }); } ``` ## FormBuilder Patterns ### Nested FormGroups ```typescript @Component({ imports: [ReactiveFormsModule], template: ` <form [formGroup]="form" (ngSubmit)="onSubmit()"> <input formControlName="name" placeholder="Name" /> <div formGroupName="address"> <input formControlName="street" placeholder="Street" /> <input formControlName="city" placeholder="City" /> <input formControlName="zip" placeholder="ZIP" /> </div> <button type="submit">Submit</button> </form> `, }) export class Profile { private fb = inject(NonNullableFormBuilder); form = this.fb.group({ name: ['', Validators.required], address: this.fb.group({ street: [''], city: ['', Validators.required], zip: ['', [Validators.required, Validators.pattern(/^\d{5}$/)]], }), }); } ``` ## Dynamic Forms with FormArray ```typescript import { FormArray } from '@angular/forms'; @Component({ imports: [ReactiveFormsModule], template: ` <form [form