angular / angular/components

Proposal: Decouple autocomplete from the form control

オープン
#12,144 コメント 4 件 リアクション 24 件 担当者 0 名 GitHub で見る
area: material/autocomplete feature G P3
主要言語
TypeScript
スター
25k
フォーク
6.8k
平均マージ
1日 8時間
マージ済み PR(30日)
91

説明

### Motivation

Suppose you have a text input that should contain a space separated list of options. As the user is typing the next option the autocomplete should suggest a completion and on picking one it replaces the current word being typed. Real world examples would be the "To" field for email or a search input with multiple keywords and you want to autocomplete only one part of the bigger query string.

With the current API this is hard to implement because the autocomplete effectively hijacks the input field from you and writes directly to it giving you no control on how that selected mat-option should affect the value.

### Proposal

Decouple the autocomplete from the form input so that it doesn't write the form control value directly and leave it up to the containing component to decide what to write on "optionSelected". The above example could then be implemented with something like

```html


{{option}}

```

```ts
@Component({
selector: 'autocomplete-filter-example',
templateUrl: 'autocomplete-filter-example.html',
styleUrls: ['autocomplete-filter-example.css'],
})
export class AutocompleteFilterExample {
options: string[] = ['One', 'Two', 'Three'];
myControl = new FormControl('');
filteredOptions = this.myControl.valueChanges
.pipe(
map(value => this.currentWord(value)),
map(current => this._filter(current)));

currentWord(value: string): string {
const words = value.split(' ');
if (words.length === 0) {
return value;
} else {
return words[words.length - 1];
}
}

private _filter(value: string): string[] {
const filterValue = value.toLowerCase();
return this.options.filter(
option => option.toLowerCase().includes(filterValue)
);
}

addOption(option: string): void {
const value = this.myControl.value as string;
const words = value.split(' ');
if (words.length === 0){
this.myControl.setValue(option);
} else {
words[words.length - 1] = option;
this.myControl.setValue(words.join(' '));
}
}
}
```

To see what the current behavior is with the above code: https://stackblitz.com/edit/angular-gaktkz

I believe these are all related issues:

Trying to achieve the above using "displayWith":
https://github.com/angular/material2/issues/11796
https://github.com/angular/material2/issues/8436

Not exactly same use case as above but would be solved be decoupling autocomplete and the form control:
https://github.com/angular/material2/issues/4863

Autocomplete overwriting the value that's being set via formControl.setValue(...)
https://github.com/angular/material2/issues/10968
https://github.com/angular/material2/issues/8214

コントリビューションガイド

コントリビューションガイドを開く

調査の方向性

まず autocomplete コンポーネントの API と、displayWith および value の上書きに関する関連 issue を確認します。現在の動作を提供された StackBlitz の例と比較し、optionSelected がフォームコントロールとどのように連携すべきかを判断します。提案された複数語 autocomplete のユースケースで、autocomplete に上書きされることなく、選択したオプションの結果の値を制御できれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
angular, typescript
領域
frontend
issue の種類
機能追加
難易度
5/5
見積もり時間
1週間以上
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
25/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。