angular / angular/components

Proposal: Decouple autocomplete from the form control

Đang mở
#12,144 4 bình luận 24 reaction 0 người được giao Xem trên GitHub
area: material/autocomplete feature G P3
Ngôn ngữ chính
TypeScript
Star
25k
Fork
6.8k
Merge trung bình
1 ngày 8 giờ
Pull request đã merge (30 ngày)
91

Mô tả

### 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

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Hướng nghiên cứu

Bắt đầu bằng việc xem xét API của component autocomplete và các issue liên quan về displayWith cũng như việc ghi đè value. So sánh hành vi hiện tại với ví dụ StackBlitz được cung cấp và xác định optionSelected nên tương tác với form control như thế nào. Công việc được xem là hoàn tất khi use case autocomplete nhiều từ được đề xuất có thể kiểm soát giá trị kết quả của tùy chọn đã chọn mà không bị autocomplete ghi đè.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
angular, typescript
Lĩnh vực
frontend
Loại issue
Tính năng
Độ khó
5/5
Thời gian dự kiến
Hơn một tuần
Mức độ hoạt động
Đình trệ
Độ rõ ràng
Khá rõ ràng
Mức phù hợp với người mới
25/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.