mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-05-13 16:13:03 +08:00
feat: salvage Angular developer skill
This commit is contained in:
committed by
Affaan Mustafa
parent
14816289ba
commit
456bbd12e5
122
skills/angular-developer/references/reactive-forms.md
Normal file
122
skills/angular-developer/references/reactive-forms.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# Reactive Forms
|
||||
|
||||
Reactive forms provide a model-driven approach to handling form inputs. They are built around observable streams and provide synchronous access to the data model, making them more scalable and testable than template-driven forms.
|
||||
|
||||
## Core Classes
|
||||
|
||||
Reactive forms are built using these fundamental classes from `@angular/forms`:
|
||||
|
||||
- `FormControl`: Manages the value and validity of an individual input.
|
||||
- `FormGroup`: Manages a group of controls (an object-like structure).
|
||||
- `FormArray`: Manages a numerically indexed array of controls.
|
||||
- `FormBuilder`: A service that provides factory methods for creating control instances.
|
||||
|
||||
## Setup
|
||||
|
||||
Import `ReactiveFormsModule` into your component.
|
||||
|
||||
```ts
|
||||
import {Component, inject} from '@angular/core';
|
||||
import {ReactiveFormsModule, FormGroup, FormControl, Validators, FormBuilder} from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'app-profile-editor',
|
||||
imports: [ReactiveFormsModule],
|
||||
templateUrl: './profile-editor.component.html',
|
||||
})
|
||||
export class ProfileEditor {
|
||||
private fb = inject(FormBuilder);
|
||||
|
||||
// Using FormBuilder for concise definition
|
||||
profileForm = this.fb.group({
|
||||
firstName: ['', Validators.required],
|
||||
lastName: [''],
|
||||
address: this.fb.group({
|
||||
street: [''],
|
||||
city: [''],
|
||||
}),
|
||||
aliases: this.fb.array([this.fb.control('')]),
|
||||
});
|
||||
|
||||
onSubmit() {
|
||||
console.warn(this.profileForm.value);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Template Binding
|
||||
|
||||
Use directives to bind the model to the view:
|
||||
|
||||
- `[formGroup]`: Binds a `FormGroup` to a `<form>` or `<div>`.
|
||||
- `formControlName`: Binds a named control within a group to an input.
|
||||
- `formGroupName`: Binds a nested `FormGroup`.
|
||||
- `formArrayName`: Binds a nested `FormArray`.
|
||||
- `[formControl]`: Binds a standalone `FormControl`.
|
||||
|
||||
```html
|
||||
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
|
||||
<input type="text" formControlName="firstName" />
|
||||
|
||||
<div formGroupName="address">
|
||||
<input type="text" formControlName="street" />
|
||||
</div>
|
||||
|
||||
<div formArrayName="aliases">
|
||||
@for (alias of aliases.controls; track $index) {
|
||||
<input type="text" [formControlName]="$index" />
|
||||
}
|
||||
</div>
|
||||
|
||||
<button type="submit" [disabled]="!profileForm.valid">Submit</button>
|
||||
</form>
|
||||
```
|
||||
|
||||
## Accessing Controls
|
||||
|
||||
Use getters for easy access to controls, especially for `FormArray`.
|
||||
|
||||
```ts
|
||||
get aliases() {
|
||||
return this.profileForm.get('aliases') as FormArray;
|
||||
}
|
||||
|
||||
addAlias() {
|
||||
this.aliases.push(this.fb.control(''));
|
||||
}
|
||||
```
|
||||
|
||||
## Updating Values
|
||||
|
||||
- `patchValue()`: Updates only the specified properties. Fails silently on structural mismatches.
|
||||
- `setValue()`: Replaces the entire model. Strictly enforces the form structure.
|
||||
|
||||
```ts
|
||||
updateProfile() {
|
||||
this.profileForm.patchValue({
|
||||
firstName: 'Nancy',
|
||||
address: { street: '123 Drew Street' }
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Unified Change Events
|
||||
|
||||
Modern Angular (v18+) provides a single `events` observable on all controls to track value, status, pristine, touched, reset, and submit events.
|
||||
|
||||
```ts
|
||||
import {ValueChangeEvent, StatusChangeEvent} from '@angular/forms';
|
||||
|
||||
this.profileForm.events.subscribe((event) => {
|
||||
if (event instanceof ValueChangeEvent) {
|
||||
console.log('New value:', event.value);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Manual State Management
|
||||
|
||||
- `markAsTouched()` / `markAllAsTouched()`: Useful for showing validation errors on submit.
|
||||
- `markAsDirty()` / `markAsPristine()`: Tracks if the value has been modified.
|
||||
- `updateValueAndValidity()`: Manually triggers recalculation of value and status.
|
||||
- Options `{ emitEvent: false }` or `{ onlySelf: true }` can be passed to most methods to control propagation.
|
||||
Reference in New Issue
Block a user