Autocompletar material angular usando una matriz <Objeto>
Tengo el siguiente Stackblitz: AutoComplete - StackBlitz
Una vez que un usuario selecciona una opción, luego borra la entrada y comienza a escribir, el filtrado deja de funcionar.
¿Cómo puede un usuario seleccionar una opción y comenzar a escribir donde solo se muestran los resultados válidos?
Respuestas
Deja de funcionar porque recibe un error en el flujo de rxjs.
valuepuede ser un objeto stringo option. Tienes que mapearlo correctamente a través del mapoperador:
En vez de
.pipe(
startWith(''),
map(value => this._filter(value))
);
prueba lo siguiente:
.pipe(
startWith(''),
map(value => typeof value === 'string' ? value : value.address),
map(address => address ? this._filter(address) : this.options.slice())
);
Forker Stackblitz
Consulte también Ejemplo de autocompletado de valor de visualización en documentos de material angular
Actualizar
OP cree que esta implementación tiene un problema:
Bifurqué el tuyo nuevamente y agregué un botón solo para facilitarme. Si selecciona una opción, haga clic en continuar, retroceda el "0" del código postal, haga clic en continuar, agregue el cero de nuevo a la entrada, haga clic en continuar. Esto te da indefinidohttps://stackblitz.com/edit/angular-material-autocomplete-eg-4w15ki?file=app/autocomplete-filter-example.html
Pero si verifica los documentos de material, funciona como se esperaba porque no hay una función de selección de coincidencia o selección de fuerza en el autocompletado de material angular https://github.com/angular/components/issues/3334
Esto significa que si está escribiendo y la cadena escrita coincide exactamente con el valor en autocompletar, el valor de FormControl seguirá siendo una cadena, no un objeto como esperaba.
Para forzarlo, puede crear una directiva simple como:
@Directive({
selector: "[forceSelection]"
})
export class AutocompleteForceSelectionDirective implements AfterViewInit, OnDestroy {
@Input() matAutocomplete: MatAutocomplete;
@Input('forceSelection') key: string;
private destroyed$ = new Subject(); constructor( @Host() @Self() private autoCompleteTrigger: MatAutocompleteTrigger, private ngControl: NgControl ) {} ngAfterViewInit() { this.autoCompleteTrigger.panelClosingActions .pipe( filter(e => !e || !e.source), takeUntil(this.destroyed$)
)
.subscribe(e => {
const selected = this.matAutocomplete.options
.map(option => option.value)
.find(option => (this.key ? option[this.key] : option) === this.ngControl.value);
if (selected) {
this.ngControl.control.setValue(selected);
}
});
}
ngOnDestroy() {
this.destroyed$.next();
}
}
Y aplícalo a tu entrada
<input ... [matAutocomplete]="auto" forceSelection="address">
https://stackblitz.com/edit/angular-material-autocomplete-eg-lih2bo?file=app%2Fautocomplete-force-selection.directive.ts