Preenchimento Automático de Material Angular usando um Array <Object>

Aug 26 2020

Eu tenho o seguinte Stackblitz: AutoComplete - StackBlitz

Depois que um usuário seleciona uma opção, limpa a entrada e começa a digitar, a filtragem para de funcionar.

Como um usuário pode selecionar uma opção e começar a digitar onde apenas os resultados válidos são exibidos?

Respostas

1 yurzui Aug 26 2020 at 01:22

Ele para de funcionar porque você está recebendo um erro no stream rxjs.

valuepode ser um objeto stringou option. Você deve mapeá-lo corretamente por meio do mapoperador:

Ao invés de

.pipe(
  startWith(''),
  map(value => this._filter(value))
);

tente o seguinte:

.pipe(
  startWith(''),
  map(value => typeof value === 'string' ? value : value.address),
  map(address => address ? this._filter(address) : this.options.slice())
);

Forker Stackblitz

Veja também o exemplo de preenchimento automático de valor de exibição em documentos de material angular

Atualizar

O OP acha que esta implementação tem um problema:

Retirei o seu novamente e adicionei um botão apenas para facilitar. Se você selecionar uma opção, clique em continuar, retroceda o "0" do código postal, clique em continuar, adicione o zero de volta à entrada e clique em continuar. Isso dá a você indefinidohttps://stackblitz.com/edit/angular-material-autocomplete-eg-4w15ki?file=app/autocomplete-filter-example.html

Mas se você verificar os documentos do material, ele funcionará conforme o esperado, pois não há nenhum recurso de seleção de correspondência ou seleção de força no preenchimento automático de material angular https://github.com/angular/components/issues/3334

Isso significa que se você estiver digitando e a string digitada corresponder exatamente ao valor no preenchimento automático, o valor do FormControl ainda será a string e não o objeto como você esperava.

Para forçá-lo, você pode criar uma diretiva simples 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();
  }
}

E aplique-o à sua entrada

<input ... [matAutocomplete]="auto" forceSelection="address">

https://stackblitz.com/edit/angular-material-autocomplete-eg-lih2bo?file=app%2Fautocomplete-force-selection.directive.ts