使用Angular Material来实现自动完成功能
首先
Angular Material中有一个叫做”自动完成”的组件。
它可以根据自由输入的内容来缩小选择器的选项。
自动补全:https://material.angular.io/components/autocomplete/overview
然而,Angular Material的自动完成功能并不是非常方便,即使输入内容与选项中的任何一个都不匹配,输入内容仍然会保留下来。
我认为,如果仅作为自由输入的辅助工具,这样就足够了,但作为选择器的过滤器来说并不理想。
选择器:https://material.angular.io/components/select/overview
在研究后发现确实存在一种名为ng-select的组件,但是它与Angular Material组件的配合并不理想。(特别是mat-form-field)
我使用Angular Material创建了一个可以作为选择器过滤器的自动完成。
我根据React的MUI中的Autocomplete创建了这个。
完成任务
实施
HTML (HyperText Markup Language) is a standard markup language used for creating and structuring web pages.
<form>
<mat-form-field appearance="fill">
<mat-label>ラベル</mat-label>
<input
type="text"
matInput
#InputField="matInput"
[formControl]="myControl"
[matAutocomplete]="auto"
/>
<mat-icon matSuffix
>{{ InputField.focused ? 'expand_less' : 'expand_more' }}</mat-icon
>
<mat-autocomplete
autoActiveFirstOption
#auto="matAutocomplete"
[displayWith]="autoCompleteDisplayFn"
(closed)="onCloseAutoCompleteOptions()"
>
<mat-option
*ngFor="let option of filteredOptions | async"
[value]="option"
[ngClass]="_allowSelection(option.id)"
>
{{option.value}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</form>
CSS (Cascading Style Sheets) is a coding language used to design and style webpages.
.no-data-auto-complete {
pointer-events: none;
color: gray;
}
TypeScript -> TypeScript
import { Component, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Observable, of } from 'rxjs';
import { map, startWith, filter } from 'rxjs/operators';
interface ItemType {
id: number;
value: string;
}
@Component({
selector: 'autocomplete-auto-active-first-option-example',
templateUrl: 'autocomplete-auto-active-first-option-example.html',
styleUrls: ['autocomplete-auto-active-first-option-example.css'],
})
export class AutocompleteAutoActiveFirstOptionExample implements OnInit {
myControl = new FormControl<string | ItemType>('');
options: ItemType[] = [
{ id: 1, value: 'aaa' },
{ id: 2, value: 'bbb' },
{ id: 3, value: 'ccc' },
];
filteredOptions: Observable<ItemType[]> = of([]);
ngOnInit() {
this.filteredOptions = this.myControl.valueChanges.pipe(
startWith(''),
filter((x): x is string | ItemType => x != null),
map((x: string | ItemType) => (typeof x === 'string' ? x : x.value)),
map((x: string) => {
if (x === '') {
return [...this.options];
}
// 部分一致
const filteredItemList = this.options.filter((i) =>
i.value.includes(x)
);
return filteredItemList.length > 0
? filteredItemList
: [{ id: -1, value: 'not found' }];
})
);
}
autoCompleteDisplayFn(item?: ItemType | null): string {
return item ? item.value : '';
}
onCloseAutoCompleteOptions(): void {
if (typeof this.myControl.value === 'string') {
this.myControl.setValue('');
}
}
_allowSelection(id: number): { [className: string]: boolean } {
return {
'no-data-auto-complete': id === -1,
};
}
}
-
- 何も見つからなかったときは id = -1 を入れています
-
- 今回は入力内容の部分一致で選択肢を絞っています
startWith(”) を入れることで、仮に最初から値が入っていたとしても、最初に限りすべての選択肢の中から選べるようにしてあります
あくまで選択肢のためのフィルタであって欲しいため、選択肢と完全一致している文字列が入力されていても選択肢をクリックしなければ、選択していないものとして扱います
なにも値が存在しないときに not found を入れることで closed が発火するようにしています(選択肢がないとフォームから関心が外れても選択肢が畳まれないため closed は発火しない)
请凭此为参考
- angular/components#13013