Preenchimento Automático de Material Angular usando um Array <Object>
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
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