feat: add Angular NgRx best practices documentation

This commit is contained in:
Dennis Hundertmark
2026-03-08 08:51:02 +01:00
parent 67dc823270
commit 2184971175
47 changed files with 8490 additions and 0 deletions
@@ -0,0 +1,107 @@
# Angular Signal Forms - ( FormValueControl )
## Table of Contents
- [Signal Form FormValueControl](#formValueControl)
## Signal Forms FormValueControl
```typescript
interface Rating {
rating: number;
}
import {
form,
FormField,
FormValueControl,
ValidationError,
WithOptionalField,
} from "@angular/forms/signals";
import { MatIconModule } from "@angular/material/icon";
import { MatError } from "@angular/material/form-field";
@Component({
selector: "app-rating",
imports: [MatIconModule, MatError],
template: `
<div class="star-rating-container">
@for (star of starArray(); track $index) {
<mat-icon
(click)="rate(star)"
class="star-icon"
[class.readonly]="readonly()"
[class.error]="invalid()"
[class]="{ filled: star <= value() }"
>
{{ getStarIcon(star) }}
</mat-icon>
}
@if (errors().at(0)?.message) {
<mat-error>
{{ errors().at(0)?.message }}
</mat-error>
}
</div>
`,
styles: ``,
})
export class Rating implements FormValueControl<number> {
// Required: The value of the control, exposed as a two-way binding.
readonly value = model<number>(0);
// Optional: Bindings for other form control states.
readonly readonly = input<boolean>(false);
readonly invalid = input<boolean>(false);
readonly errors: InputSignal<readonly WithOptionalField<ValidationError>[]> =
input<readonly WithOptionalField<ValidationError>[]>([]);
starArray: Signal<number[]> = signal(
Array(5)
.fill(0)
.map((_, i) => i + 1),
);
getStarIcon(index: number): string {
const floorRating = Math.floor(this.value());
if (index <= floorRating) {
return "star"; // Full star
} else {
return "star_border"; // Empty star
}
}
rate(index: number): void {
if (!this.readonly()) {
this.value.set(index);
}
}
}
import { FormField } from "@angular/forms/signals";
@Component({
selector: "app-signal-forms",
imports: [FormField, Rating],
template: `
<form autocomplete="off" (submit)="submit($event)">
<div class="form-field">
<app-rating [formField]="ratingForm.rating"> </app-rating>
<!-- print to show the value updation -->
{{ ratingForm.rating().value() }}
</div>
</form>
`,
styles: ``,
})
export class SignalForms {
readonly ratingModel = signal<Rating>({
rating: 0,
});
readonly ratingForm = form(this.ratingModel);
submit(event: Event): void {
event.preventDefault();
console.log(this.ratingForm.rating().value());
}
}
```