Autocompletar material angular usando una matriz <Objeto>

Aug 26 2020

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

1 yurzui Aug 26 2020 at 01:22

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