From c4d15a85c9376184f597bbe7374d334fcdebd381 Mon Sep 17 00:00:00 2001 From: Michael Small Date: Mon, 3 Aug 2026 18:04:42 -0500 Subject: [PATCH] docs: add signal forms examples to Checkbox and Chips --- .../checkbox-signal-forms-example.css | 3 + .../checkbox-signal-forms-example.html | 11 ++++ .../checkbox-signal-forms-example.ts | 21 +++++++ .../material/checkbox/index.ts | 1 + .../chips-form-control-example.html | 2 +- .../chips-form-field-example.css | 7 +++ .../chips-form-field-example.html | 31 ++++++++++ .../chips-form-field-example.ts | 56 +++++++++++++++++++ .../chips-reactive-form-example.html | 2 +- .../chips-signal-form-example.css | 3 + .../chips-signal-form-example.html | 21 +++++++ .../chips-signal-form-example.ts | 46 +++++++++++++++ .../chips-template-form-example.html | 2 +- .../material/chips/index.ts | 2 + src/material/checkbox/checkbox.md | 5 +- src/material/chips/chips.md | 6 +- 16 files changed, 210 insertions(+), 9 deletions(-) create mode 100644 src/components-examples/material/checkbox/checkbox-signal-forms/checkbox-signal-forms-example.css create mode 100644 src/components-examples/material/checkbox/checkbox-signal-forms/checkbox-signal-forms-example.html create mode 100644 src/components-examples/material/checkbox/checkbox-signal-forms/checkbox-signal-forms-example.ts create mode 100644 src/components-examples/material/chips/chips-form-field/chips-form-field-example.css create mode 100644 src/components-examples/material/chips/chips-form-field/chips-form-field-example.html create mode 100644 src/components-examples/material/chips/chips-form-field/chips-form-field-example.ts create mode 100644 src/components-examples/material/chips/chips-signal-form/chips-signal-form-example.css create mode 100644 src/components-examples/material/chips/chips-signal-form/chips-signal-form-example.html create mode 100644 src/components-examples/material/chips/chips-signal-form/chips-signal-form-example.ts diff --git a/src/components-examples/material/checkbox/checkbox-signal-forms/checkbox-signal-forms-example.css b/src/components-examples/material/checkbox/checkbox-signal-forms/checkbox-signal-forms-example.css new file mode 100644 index 000000000000..91b7e24fc2db --- /dev/null +++ b/src/components-examples/material/checkbox/checkbox-signal-forms/checkbox-signal-forms-example.css @@ -0,0 +1,3 @@ +.example-section { + margin: 12px 0; +} diff --git a/src/components-examples/material/checkbox/checkbox-signal-forms/checkbox-signal-forms-example.html b/src/components-examples/material/checkbox/checkbox-signal-forms/checkbox-signal-forms-example.html new file mode 100644 index 000000000000..6e4771f0247d --- /dev/null +++ b/src/components-examples/material/checkbox/checkbox-signal-forms/checkbox-signal-forms-example.html @@ -0,0 +1,11 @@ +
+

Select your toppings:

+

Pepperoni

+

Extra Cheese

+

Mushroom

+
+ +
+

You chose:

+ {{toppingsForm().value() | json}} +
diff --git a/src/components-examples/material/checkbox/checkbox-signal-forms/checkbox-signal-forms-example.ts b/src/components-examples/material/checkbox/checkbox-signal-forms/checkbox-signal-forms-example.ts new file mode 100644 index 000000000000..ab1ff449327b --- /dev/null +++ b/src/components-examples/material/checkbox/checkbox-signal-forms/checkbox-signal-forms-example.ts @@ -0,0 +1,21 @@ +import {JsonPipe} from '@angular/common'; +import {Component, signal} from '@angular/core'; +import {form, FormField} from '@angular/forms/signals'; +import {MatCheckboxModule} from '@angular/material/checkbox'; + +/** @title Checkboxes with signal forms */ +@Component({ + selector: 'checkbox-signal-forms-example', + templateUrl: 'checkbox-signal-forms-example.html', + styleUrl: 'checkbox-signal-forms-example.css', + imports: [FormField, MatCheckboxModule, JsonPipe], +}) +export class CheckboxSignalFormsExample { + readonly toppingsFormModel = signal({ + pepperoni: false, + extracheese: false, + mushroom: false, + }); + + readonly toppingsForm = form(this.toppingsFormModel); +} diff --git a/src/components-examples/material/checkbox/index.ts b/src/components-examples/material/checkbox/index.ts index 892a553a3be2..fc33c52bf3dd 100644 --- a/src/components-examples/material/checkbox/index.ts +++ b/src/components-examples/material/checkbox/index.ts @@ -2,3 +2,4 @@ export {CheckboxConfigurableExample} from './checkbox-configurable/checkbox-conf export {CheckboxHarnessExample} from './checkbox-harness/checkbox-harness-example'; export {CheckboxOverviewExample} from './checkbox-overview/checkbox-overview-example'; export {CheckboxReactiveFormsExample} from './checkbox-reactive-forms/checkbox-reactive-forms-example'; +export {CheckboxSignalFormsExample} from './checkbox-signal-forms/checkbox-signal-forms-example'; diff --git a/src/components-examples/material/chips/chips-form-control/chips-form-control-example.html b/src/components-examples/material/chips/chips-form-control/chips-form-control-example.html index 4cae76b49fca..b45ddc4c9657 100644 --- a/src/components-examples/material/chips/chips-form-control/chips-form-control-example.html +++ b/src/components-examples/material/chips/chips-form-control/chips-form-control-example.html @@ -8,7 +8,7 @@ Video keywords - @for (keyword of keywords(); track keyword) { + @for (keyword of keywords(); track $index) { {{keyword}} + + +

+ Enter video keywords +

+ + Video keywords + + @for (keyword of keywordsForm.words().value(); track $index) { + + {{ keyword }} + + + } + + + + +

The following keywords are entered: {{ keywordsForm.words().value() }}

\ No newline at end of file diff --git a/src/components-examples/material/chips/chips-form-field/chips-form-field-example.ts b/src/components-examples/material/chips/chips-form-field/chips-form-field-example.ts new file mode 100644 index 000000000000..6c375ac6ac49 --- /dev/null +++ b/src/components-examples/material/chips/chips-form-field/chips-form-field-example.ts @@ -0,0 +1,56 @@ +import {LiveAnnouncer} from '@angular/cdk/a11y'; +import {Component, inject, signal} from '@angular/core'; +import {disabled, form, FormField} from '@angular/forms/signals'; +import {MatButtonModule} from '@angular/material/button'; +import {MatChipInputEvent, MatChipsModule} from '@angular/material/chips'; +import {MatFormFieldModule} from '@angular/material/form-field'; +import {MatIconModule} from '@angular/material/icon'; + +/** + * @title Chips with form field + */ +@Component({ + selector: 'chips-form-field-example', + templateUrl: 'chips-form-field-example.html', + styleUrl: 'chips-form-field-example.css', + imports: [FormField, MatButtonModule, MatFormFieldModule, MatChipsModule, MatIconModule], +}) +export class ChipsFormFieldExample { + readonly keywordsFormModel = signal({ + words: ['angular', 'how-to', 'tutorial', 'accessibility'], + enabled: true, + }); + + readonly keywordsForm = form(this.keywordsFormModel, p => { + disabled(p, { + when: ({valueOf}) => !valueOf(p.enabled), + }); + }); + + announcer = inject(LiveAnnouncer); + + protected removeKeyword(keyword: string) { + this.keywordsFormModel.update(keywords => { + const index = keywords.words.indexOf(keyword); + if (index < 0) { + return keywords; + } + + keywords.words.splice(index, 1); + this.announcer.announce(`removed ${keyword}`); + return {...keywords}; + }); + } + + protected add(event: MatChipInputEvent): void { + const value = (event.value || '').trim(); + + // Add our keyword + if (value) { + this.keywordsFormModel.update(keywords => ({...keywords, words: [...keywords.words, value]})); + } + + // Clear the input value + event.chipInput!.clear(); + } +} diff --git a/src/components-examples/material/chips/chips-reactive-form/chips-reactive-form-example.html b/src/components-examples/material/chips/chips-reactive-form/chips-reactive-form-example.html index 7b9b699e0f1b..3619ad6c60e8 100644 --- a/src/components-examples/material/chips/chips-reactive-form/chips-reactive-form-example.html +++ b/src/components-examples/material/chips/chips-reactive-form/chips-reactive-form-example.html @@ -3,7 +3,7 @@

Chips inside of a Reactive form

Video keywords - @for (keyword of formControl.value; track keyword) { + @for (keyword of formControl.value; track $index) { {{keyword}} + + } + + + + diff --git a/src/components-examples/material/chips/chips-signal-form/chips-signal-form-example.ts b/src/components-examples/material/chips/chips-signal-form/chips-signal-form-example.ts new file mode 100644 index 000000000000..4c8e8e2a76bc --- /dev/null +++ b/src/components-examples/material/chips/chips-signal-form/chips-signal-form-example.ts @@ -0,0 +1,46 @@ +import {LiveAnnouncer} from '@angular/cdk/a11y'; +import {Component, inject, signal} from '@angular/core'; +import {form, FormField} from '@angular/forms/signals'; +import {MatButtonModule} from '@angular/material/button'; +import {MatChipInputEvent, MatChipsModule} from '@angular/material/chips'; +import {MatFormFieldModule} from '@angular/material/form-field'; +import {MatIconModule} from '@angular/material/icon'; + +/** + * @title Chips in signal forms + */ +@Component({ + selector: 'chips-signal-form-example', + templateUrl: 'chips-signal-form-example.html', + styleUrl: 'chips-signal-form-example.css', + imports: [FormField, MatButtonModule, MatFormFieldModule, MatChipsModule, MatIconModule], +}) +export class ChipsSignalFormExample { + private _announcer = inject(LiveAnnouncer); + + readonly keywordsFormModel = signal(['angular', 'how-to', 'tutorial', 'accessibility']); + + readonly keywordsForm = form(this.keywordsFormModel); + + protected addKeyword(event: MatChipInputEvent): void { + const value = (event.value || '').trim(); + + if (value) { + this.keywordsFormModel.update(model => [...model, value]); + this._announcer.announce(`added ${value} to signal form`); + } + + event.chipInput.clear(); + } + + protected removeKeyword(keyword: string) { + const keywords = this.keywordsForm().value(); + const index = keywords.lastIndexOf(keyword); + + if (index > -1) { + keywords.splice(index, 1); + this.keywordsFormModel.set(keywords); + this._announcer.announce(`removed ${keyword} from signal form`); + } + } +} diff --git a/src/components-examples/material/chips/chips-template-form/chips-template-form-example.html b/src/components-examples/material/chips/chips-template-form/chips-template-form-example.html index 1feb99194dfc..9253790a9e0d 100644 --- a/src/components-examples/material/chips/chips-template-form/chips-template-form-example.html +++ b/src/components-examples/material/chips/chips-template-form/chips-template-form-example.html @@ -3,7 +3,7 @@

Chips inside of a Template-driven form

Video keywords - @for (keyword of keywords(); track keyword) { + @for (keyword of keywords(); track $index) { {{keyword}}