Skip to content
Back to skills

Ng22 Signal Forms

ASecurity

Enforces Angular 22 signal-centric form patterns, computed validation mapping, and controlled state mutation.

  • 2 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 6, 2026
developmenttypescriptreactangular

Security analysis

A100/100

Scanned September 6, 2026

npx -y skills add PavanAnguluri/angular22-agent-skills --skill ng22-signal-forms --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ng22 Signal Forms?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Ng22 Signal Forms
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/pavananguluri-ng22-signal-forms/badge)](https://www.skillsdirectory.com/skills/pavananguluri-ng22-signal-forms)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: ng22-signal-forms
description: Enforces Angular 22 signal-centric form patterns, computed validation mapping, and controlled state mutation.
---

# Angular 22 Signal-Centric Forms

Build forms with explicit reactive state and avoid fallback to legacy patterns. Treat each form as a signal-driven data model with deterministic validation and update flow.

## Core Rules

1. Do not default to `FormBuilder` or template-driven forms for new complex workflows.
2. Keep primary form state in signals and derive view state with `computed()`.
3. Model validation errors as computed maps so error rendering is deterministic and centralized.
4. Use signal inputs to seed initial control values and keep initialization explicit.
5. Keep form arrays trackable with signal-backed collections and immutable updates.

## Signal Input Initialization Pattern

```typescript
import { Component, computed, input, signal } from '@angular/core';

type ProfileForm = {
  name: string;
  aliases: string[];
};

@Component({
  standalone: true,
  selector: 'app-profile-form',
  template: `
    <input [value]="form().name" (input)="setName($any($event.target).value)" />

    @for (alias of form().aliases; track $index; let i = $index) {
      <input [value]="alias" (input)="setAlias(i, $any($event.target).value)" />
    }

    @if (errors().name) {
      <p>{{ errors().name }}</p>
    }
  `,
})
export class ProfileFormComponent {
  initialName = input<string>('');
  initialAliases = input<string[]>([]);

  form = signal<ProfileForm>({
    name: this.initialName(),
    aliases: [...this.initialAliases()],
  });

  errors = computed(() => {
    const value = this.form();

    return {
      name: value.name.trim().length < 2 ? 'Name must be at least 2 characters.' : '',
      aliases: value.aliases.map((alias) =>
        alias.trim().length === 0 ? 'Alias cannot be empty.' : ''
      ),
    };
  });

  setName(name: string): void {
    this.form.update((value) => ({ ...value, name }));
  }

  setAlias(index: number, alias: string): void {
    this.form.update((value) => ({
      ...value,
      aliases: value.aliases.map((current, i) => (i === index ? alias : current)),
    }));
  }
}
```

## Form Array Mutation Discipline

- Add rows with immutable operations such as `aliases: [...aliases, '']`.
- Remove rows with index-filtered copies, never in-place mutation.
- Keep the rendered list keyed with stable tracking (`track item.id`) when available.

## Validation Mapping Pattern

- Derive all validation state in one `computed()` tree.
- Keep field-level and cross-field rules together so templates remain simple.
- Keep error text generation centralized to avoid duplicated string logic in templates.

## Anti-Patterns

- Mixing template-driven directives with signal-first form state.
- Triggering hidden side effects from validators.
- Mutating arrays or nested objects in place and expecting deterministic updates.
- Spreading validation logic across template fragments.

## Review Checklist

- Form state is signal-backed.
- Validation is computed and centralized.
- Arrays are updated immutably and tracked correctly.
- Initialization uses explicit signal inputs.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.