Skip to content

Commit

Permalink
docs(material/chips): describe how to use chips in forms
Browse files Browse the repository at this point in the history
Added a description and examples in the docs of how to use chips in both reactive and template-driven forms.

Fixes angular#22906
  • Loading branch information
HermanWKeuris committed Jul 8, 2024
1 parent e6535b7 commit ff72b61
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.example-form-field {
width: 100%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<section>
<h4>Chips inside of a Reactive form</h4>
<mat-form-field class="example-form-field">
<mat-label>Video keywords</mat-label>
<mat-chip-grid #reactiveChipGrid aria-label="Enter reactive form keywords" [formControl]="formControl">
@for (keyword of reactiveKeywords(); track keyword) {
<mat-chip-row (removed)="removeReactiveKeyword(keyword)">
{{keyword}}
<button matChipRemove aria-label="'remove reactive form' + keyword">
<mat-icon>cancel</mat-icon>
</button>
</mat-chip-row>
}
</mat-chip-grid>
<input
placeholder="New keyword..."
[matChipInputFor]="reactiveChipGrid"
(matChipInputTokenEnd)="addReactiveKeyword($event)"
/>
</mat-form-field>
</section>
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import {LiveAnnouncer} from '@angular/cdk/a11y';
import {ChangeDetectionStrategy, Component, inject, signal} from '@angular/core';
import {FormControl, ReactiveFormsModule} from '@angular/forms';
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 reactive forms
*/
@Component({
selector: 'chips-reactive-form-example',
templateUrl: 'chips-reactive-form-example.html',
styleUrl: 'chips-reactive-form-example.css',
standalone: true,
imports: [
MatButtonModule,
MatFormFieldModule,
MatChipsModule,
ReactiveFormsModule,
MatIconModule,
],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ChipsReactiveFormExample {
readonly reactiveKeywords = signal(['angular', 'how-to', 'tutorial', 'accessibility']);
readonly formControl = new FormControl(['angular']);

announcer = inject(LiveAnnouncer);

removeReactiveKeyword(keyword: string) {
this.reactiveKeywords.update(keywords => {
const index = keywords.indexOf(keyword);
if (index < 0) {
return keywords;
}

keywords.splice(index, 1);
this.announcer.announce(`removed ${keyword} from reactive form`);
return [...keywords];
});
}

addReactiveKeyword(event: MatChipInputEvent): void {
const value = (event.value || '').trim();

// Add our keyword
if (value) {
this.reactiveKeywords.update(keywords => [...keywords, value]);
this.announcer.announce(`added ${value} to reactive form`);
}

// Clear the input value
event.chipInput!.clear();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.example-form-field {
width: 100%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<section>
<h4>Chips inside of a Template-driven form</h4>
<mat-form-field class="example-form-field">
<mat-label>Video keywords</mat-label>
<mat-chip-grid #templateChipGrid aria-label="Enter template form keywords" [(ngModel)]="templateKeywords">
@for (keyword of templateKeywords(); track keyword) {
<mat-chip-row (removed)="removeTemplateKeyword(keyword)">
{{keyword}}
<button matChipRemove aria-label="'remove template form' + keyword">
<mat-icon>cancel</mat-icon>
</button>
</mat-chip-row>
}
</mat-chip-grid>
<input
placeholder="New keyword..."
[matChipInputFor]="templateChipGrid"
(matChipInputTokenEnd)="addTemplateKeyword($event)"
/>
</mat-form-field>
</section>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import {LiveAnnouncer} from '@angular/cdk/a11y';
import {ChangeDetectionStrategy, Component, inject, signal} from '@angular/core';
import {FormsModule} from '@angular/forms';
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 template-driven forms
*/
@Component({
selector: 'chips-template-form-example',
templateUrl: 'chips-template-form-example.html',
styleUrl: 'chips-template-form-example.css',
standalone: true,
imports: [MatButtonModule, MatFormFieldModule, MatChipsModule, FormsModule, MatIconModule],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ChipsTemplateFormExample {
readonly templateKeywords = signal(['angular', 'how-to', 'tutorial', 'accessibility']);

announcer = inject(LiveAnnouncer);

removeTemplateKeyword(keyword: string) {
this.templateKeywords.update(keywords => {
const index = keywords.indexOf(keyword);
if (index < 0) {
return keywords;
}

keywords.splice(index, 1);
this.announcer.announce(`removed ${keyword} from template form`);
return [...keywords];
});
}

addTemplateKeyword(event: MatChipInputEvent): void {
const value = (event.value || '').trim();

// Add our keyword
if (value) {
this.templateKeywords.update(keywords => [...keywords, value]);
this.announcer.announce(`added ${value} to template form`);
}

// Clear the input value
event.chipInput!.clear();
}
}
2 changes: 2 additions & 0 deletions src/components-examples/material/chips/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ export {ChipsOverviewExample} from './chips-overview/chips-overview-example';
export {ChipsStackedExample} from './chips-stacked/chips-stacked-example';
export {ChipsHarnessExample} from './chips-harness/chips-harness-example';
export {ChipsFormControlExample} from './chips-form-control/chips-form-control-example';
export {ChipsReactiveFormExample} from './chips-reactive-form/chips-reactive-form-example';
export {ChipsTemplateFormExample} from './chips-template-form/chips-template-form-example';
export {ChipsAvatarExample} from './chips-avatar/chips-avatar-example';
7 changes: 7 additions & 0 deletions src/material/chips/chips.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ Chips are always used inside a container. To create chips connected to an input

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

### Use with `@angular/forms`
Chips are compatible with `@angular/forms` and supports both `FormsModule`
and `ReactiveFormsModule`.

<!-- example(chips-template-form-example) -->
<!-- example(chips-reactive-form-example) -->

#### Disabled `<mat-chip-row>`

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.
Expand Down

0 comments on commit ff72b61

Please sign in to comment.