angular / angular/components

Proposal: Decouple autocomplete from the form control

Aperta
#12,144 4 commenti 24 reazioni 0 assegnatari Vedi su GitHub
area: material/autocomplete feature G P3
Lingua principale
TypeScript
Stelle
25k
Fork
6.8k
Merge medio
1g 8h
PR unite (30g)
91

Descrizione

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

Guida per i contributori

Apri la guida per i contributori

Direzione di ricerca

Inizia esaminando l’API del componente autocomplete e le issues collegate relative a displayWith e alla sovrascrittura di value. Confronta il comportamento attuale con l’esempio StackBlitz fornito e determina come optionSelected dovrebbe interagire con il controllo del modulo. Il lavoro è completato quando il caso d’uso proposto di autocomplete con più parole può controllare il valore risultante dell’opzione selezionata senza che autocomplete lo sovrascriva.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
angular, typescript
Ambito
frontend
Tipo di issue
Funzionalità
Difficoltà
5/5
Tempo stimato
Più di una settimana
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
25/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.