Files
NGRX-Playground/.agents/skills/angular-forms/references/formvalueControl-patterns.md
T

102 lines
2.9 KiB
Markdown

# 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
class="star-icon"
[class.readonly]="readonly()"
[class.error]="invalid()"
[class]="{ filled: star <= value() }"
(click)="rate(star)">
{{ 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());
}
}
```