Skip to content

Commit 26a8158

Browse files
HermanWKeuriscrisbeto
authored andcommitted
docs(material/chips): describe how to use chips in forms #22906 (#29405)
* docs(material/chips): describe how to use chips in forms Added a description and examples in the docs of how to use chips in both reactive and template-driven forms. Fixes #22906 * docs(material/chips): describe how to use chips in forms Updated indentation (cherry picked from commit 9ca2a0a)
1 parent 6f17ccd commit 26a8158

File tree

8 files changed

+164
-0
lines changed

8 files changed

+164
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.example-form-field {
2+
width: 100%;
3+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<section>
2+
<h4>Chips inside of a Reactive form</h4>
3+
<mat-form-field class="example-form-field">
4+
<mat-label>Video keywords</mat-label>
5+
<mat-chip-grid #reactiveChipGrid aria-label="Enter reactive form keywords" [formControl]="formControl">
6+
@for (keyword of reactiveKeywords(); track keyword) {
7+
<mat-chip-row (removed)="removeReactiveKeyword(keyword)">
8+
{{keyword}}
9+
<button matChipRemove aria-label="'remove reactive form' + keyword">
10+
<mat-icon>cancel</mat-icon>
11+
</button>
12+
</mat-chip-row>
13+
}
14+
</mat-chip-grid>
15+
<input
16+
placeholder="New keyword..."
17+
[matChipInputFor]="reactiveChipGrid"
18+
(matChipInputTokenEnd)="addReactiveKeyword($event)"
19+
/>
20+
</mat-form-field>
21+
</section>
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import {LiveAnnouncer} from '@angular/cdk/a11y';
2+
import {ChangeDetectionStrategy, Component, inject, signal} from '@angular/core';
3+
import {FormControl, ReactiveFormsModule} from '@angular/forms';
4+
import {MatButtonModule} from '@angular/material/button';
5+
import {MatChipInputEvent, MatChipsModule} from '@angular/material/chips';
6+
import {MatFormFieldModule} from '@angular/material/form-field';
7+
import {MatIconModule} from '@angular/material/icon';
8+
9+
/**
10+
* @title Chips in reactive forms
11+
*/
12+
@Component({
13+
selector: 'chips-reactive-form-example',
14+
templateUrl: 'chips-reactive-form-example.html',
15+
styleUrl: 'chips-reactive-form-example.css',
16+
standalone: true,
17+
imports: [
18+
MatButtonModule,
19+
MatFormFieldModule,
20+
MatChipsModule,
21+
ReactiveFormsModule,
22+
MatIconModule,
23+
],
24+
changeDetection: ChangeDetectionStrategy.OnPush,
25+
})
26+
export class ChipsReactiveFormExample {
27+
readonly reactiveKeywords = signal(['angular', 'how-to', 'tutorial', 'accessibility']);
28+
readonly formControl = new FormControl(['angular']);
29+
30+
announcer = inject(LiveAnnouncer);
31+
32+
removeReactiveKeyword(keyword: string) {
33+
this.reactiveKeywords.update(keywords => {
34+
const index = keywords.indexOf(keyword);
35+
if (index < 0) {
36+
return keywords;
37+
}
38+
39+
keywords.splice(index, 1);
40+
this.announcer.announce(`removed ${keyword} from reactive form`);
41+
return [...keywords];
42+
});
43+
}
44+
45+
addReactiveKeyword(event: MatChipInputEvent): void {
46+
const value = (event.value || '').trim();
47+
48+
// Add our keyword
49+
if (value) {
50+
this.reactiveKeywords.update(keywords => [...keywords, value]);
51+
this.announcer.announce(`added ${value} to reactive form`);
52+
}
53+
54+
// Clear the input value
55+
event.chipInput!.clear();
56+
}
57+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.example-form-field {
2+
width: 100%;
3+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<section>
2+
<h4>Chips inside of a Template-driven form</h4>
3+
<mat-form-field class="example-form-field">
4+
<mat-label>Video keywords</mat-label>
5+
<mat-chip-grid #templateChipGrid aria-label="Enter template form keywords" [(ngModel)]="templateKeywords">
6+
@for (keyword of templateKeywords(); track keyword) {
7+
<mat-chip-row (removed)="removeTemplateKeyword(keyword)">
8+
{{keyword}}
9+
<button matChipRemove aria-label="'remove template form' + keyword">
10+
<mat-icon>cancel</mat-icon>
11+
</button>
12+
</mat-chip-row>
13+
}
14+
</mat-chip-grid>
15+
<input
16+
placeholder="New keyword..."
17+
[matChipInputFor]="templateChipGrid"
18+
(matChipInputTokenEnd)="addTemplateKeyword($event)"
19+
/>
20+
</mat-form-field>
21+
</section>
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import {LiveAnnouncer} from '@angular/cdk/a11y';
2+
import {ChangeDetectionStrategy, Component, inject, signal} from '@angular/core';
3+
import {FormsModule} from '@angular/forms';
4+
import {MatButtonModule} from '@angular/material/button';
5+
import {MatChipInputEvent, MatChipsModule} from '@angular/material/chips';
6+
import {MatFormFieldModule} from '@angular/material/form-field';
7+
import {MatIconModule} from '@angular/material/icon';
8+
9+
/**
10+
* @title Chips in template-driven forms
11+
*/
12+
@Component({
13+
selector: 'chips-template-form-example',
14+
templateUrl: 'chips-template-form-example.html',
15+
styleUrl: 'chips-template-form-example.css',
16+
standalone: true,
17+
imports: [MatButtonModule, MatFormFieldModule, MatChipsModule, FormsModule, MatIconModule],
18+
changeDetection: ChangeDetectionStrategy.OnPush,
19+
})
20+
export class ChipsTemplateFormExample {
21+
readonly templateKeywords = signal(['angular', 'how-to', 'tutorial', 'accessibility']);
22+
23+
announcer = inject(LiveAnnouncer);
24+
25+
removeTemplateKeyword(keyword: string) {
26+
this.templateKeywords.update(keywords => {
27+
const index = keywords.indexOf(keyword);
28+
if (index < 0) {
29+
return keywords;
30+
}
31+
32+
keywords.splice(index, 1);
33+
this.announcer.announce(`removed ${keyword} from template form`);
34+
return [...keywords];
35+
});
36+
}
37+
38+
addTemplateKeyword(event: MatChipInputEvent): void {
39+
const value = (event.value || '').trim();
40+
41+
// Add our keyword
42+
if (value) {
43+
this.templateKeywords.update(keywords => [...keywords, value]);
44+
this.announcer.announce(`added ${value} to template form`);
45+
}
46+
47+
// Clear the input value
48+
event.chipInput!.clear();
49+
}
50+
}

src/components-examples/material/chips/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ export {ChipsOverviewExample} from './chips-overview/chips-overview-example';
55
export {ChipsStackedExample} from './chips-stacked/chips-stacked-example';
66
export {ChipsHarnessExample} from './chips-harness/chips-harness-example';
77
export {ChipsFormControlExample} from './chips-form-control/chips-form-control-example';
8+
export {ChipsReactiveFormExample} from './chips-reactive-form/chips-reactive-form-example';
9+
export {ChipsTemplateFormExample} from './chips-template-form/chips-template-form-example';
810
export {ChipsAvatarExample} from './chips-avatar/chips-avatar-example';

src/material/chips/chips.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ Chips are always used inside a container. To create chips connected to an input
4040

4141
<!-- example(chips-input) -->
4242

43+
### Use with `@angular/forms`
44+
Chips are compatible with `@angular/forms` and supports both `FormsModule`
45+
and `ReactiveFormsModule`.
46+
47+
<!-- example(chips-template-form-example) -->
48+
<!-- example(chips-reactive-form-example) -->
49+
4350
#### Disabled `<mat-chip-row>`
4451

4552
Use the `disabled` Input to disable a `<mat-chip-row>`. This gives the `<mat-chip-row>` a disabled appearance and prevents the user from interacting with it.

0 commit comments

Comments
 (0)