Skip to content

Commit 3d236a6

Browse files
committed
docs(autocomplete): add autocomplete docs (#2840)
1 parent fcc7d7f commit 3d236a6

File tree

2 files changed

+151
-5
lines changed

2 files changed

+151
-5
lines changed

src/lib/autocomplete/OVERVIEW.md

+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
2+
The autocomplete is a normal text input enhanced by a panel of suggested options. You can read more about
3+
autocompletes in the [Material Design spec](https://material.io/guidelines/components/text-fields.html#text-fields-auto-complete-text-field).
4+
5+
### Simple autocomplete
6+
7+
Start by adding a regular `mdInput` to the page. Let's assume you're using the `formControl` directive from the
8+
`@angular/forms` module to track the value of the input.
9+
10+
*my-comp.html*
11+
```html
12+
<md-input-container>
13+
<input type="text" mdInput [formControl]="myControl">
14+
</md-input-container>
15+
```
16+
17+
Next, create the autocomplete panel and the options displayed inside it. Each option should be defined by an
18+
`md-option` tag. Set each option's value property to whatever you'd like the value of the text input to be
19+
upon that option's selection.
20+
21+
*my-comp.html*
22+
```html
23+
<md-autocomplete>
24+
<md-option *ngFor="let option of options" [value]="option">
25+
{{ option }}
26+
</md-option>
27+
</md-autocomplete>
28+
```
29+
30+
Now we'll need to link the text input to its panel. We can do this by exporting the autocomplete panel instance into a
31+
local template variable (here we called it "auto"), and binding that variable to the input's `mdAutocomplete` property.
32+
33+
*my-comp.html*
34+
```html
35+
<md-input-container>
36+
<input type="text" mdInput [formControl]="myControl" [mdAutocomplete]="auto">
37+
</md-input-container>
38+
39+
<md-autocomplete #auto="mdAutocomplete">
40+
<md-option *ngFor="let option of options" [value]="option">
41+
{{ option }}
42+
</md-option>
43+
</md-autocomplete>
44+
```
45+
46+
### Adding a custom filter
47+
48+
At this point, the autocomplete panel should be toggleable on focus and options should be selectable. But if we want
49+
our options to filter when we type, we need to add a custom filter.
50+
51+
You can filter the options in any way you want based on the text input. Here we will do a simple string test on the
52+
input value to see if it matches the option value. We already have access to the built-in `valueChanges` observable on
53+
the `FormControl`, so we can simply map the text input's values to the suggested options by passing them through this
54+
filter. The resulting observable (`filteredOptions`) can be added to the template in place of the `options` property
55+
using the `async` pipe.
56+
57+
Below we are also priming our value change stream with `null` so that the options are filtered by that value on init
58+
(before there are any value changes).
59+
60+
*my-comp.ts*
61+
```ts
62+
class MyComp {
63+
myControl = new FormControl();
64+
options = [
65+
'One',
66+
'Two',
67+
'Three'
68+
];
69+
filteredOptions: Observable<string[]>;
70+
71+
ngOnInit() {
72+
this.filteredOptions = this.myControl.valueChanges
73+
.startWith(null)
74+
.map(val => val ? this.filter(val) : this.options.slice());
75+
}
76+
77+
filter(val: string): string[] {
78+
return this.options.filter(option => new RegExp(val, 'gi').test(option));
79+
}
80+
}
81+
```
82+
83+
*my-comp.html*
84+
```html
85+
<md-input-container>
86+
<input type="text" mdInput [formControl]="myControl" [mdAutocomplete]="auto">
87+
</md-input-container>
88+
89+
<md-autocomplete #auto="mdAutocomplete">
90+
<md-option *ngFor="let option of filteredOptions | async" [value]="option">
91+
{{ option }}
92+
</md-option>
93+
</md-autocomplete>
94+
```
95+
96+
### Setting separate control and display values
97+
98+
If you want the option's control value (what is saved in the form) to be different than the option's display value
99+
(what is displayed in the actual text field), you'll need to set the `displayWith` property on your autocomplete
100+
element. A common use case for this might be if you want to save your data as an object, but display just one of
101+
the option's string properties.
102+
103+
To make this work, create a function on your component class that maps the control value to the desired display value.
104+
Then bind it to the autocomplete's `displayWith` property.
105+
106+
```html
107+
<md-input-container>
108+
<input type="text" mdInput [formControl]="myControl" [mdAutocomplete]="auto">
109+
</md-input-container>
110+
111+
<md-autocomplete #auto="mdAutocomplete" [displayWith]="displayFn">
112+
<md-option *ngFor="let option of filteredOptions | async" [value]="option">
113+
{{ option }}
114+
</md-option>
115+
</md-autocomplete>
116+
```
117+
118+
*my-comp.ts*
119+
```ts
120+
class MyComp {
121+
myControl = new FormControl();
122+
options = [
123+
new User('Mary'),
124+
new User('Shelley'),
125+
new User('Igor')
126+
];
127+
filteredOptions: Observable<User[]>;
128+
129+
ngOnInit() {
130+
this.filteredOptions = this.myControl.valueChanges
131+
.startWith(null)
132+
.map(user => user && typeof user === 'object' ? user.name : user)
133+
.map(name => name ? this.filter(name) : this.options.slice());
134+
}
135+
136+
filter(name: string): User[] {
137+
return this.options.filter(option => new RegExp(name, 'gi').test(option));
138+
}
139+
140+
displayFn(user: User): string {
141+
return user ? user.name : user;
142+
}
143+
}
144+
```
145+
146+
147+
#### Keyboard interaction:
148+
- <kbd>DOWN_ARROW</kbd>: Next option becomes active.
149+
- <kbd>UP_ARROW</kbd>: Previous option becomes active.
150+
- <kbd>ENTER</kbd>: Select currently active item.

src/lib/autocomplete/README.md

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1 @@
1-
2-
## Not yet implemented!
3-
4-
The autocomplete is not yet implemented. This is only a scaffold to make
5-
subsequent PRs easier to read. Please do not try to use yet :)
1+
See documentation on [material.angular.io](https://material.angular.io/).

0 commit comments

Comments
 (0)