J'utilise angular 5 et matériau 2.
Dans le fichier ts, j'ai cette propriété:
filteredOptions: Observable<any[]>;
Cette propriété va avoir un tableau de valeurs à afficher dans le champ de saisie semi-automatique.
[{
id:'1', name: 'teste 1'},
{id:'2', name: 'teste 2'},
{id:'3', name: 'teste 3'
}]
Ce tableau de valeurs provient de la base de données et il sera affiché après que l'utilisateur ait tapé quelque chose.
fichier html:
## <form class="example-form">
## <mat-form-field class="example-full-width">
## <input type="text" placeholder="Assignee" aria-label="Assignee" matInput [formControl]="myControl" [matAutocomplete]="auto">
## <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
## <mat-option *ngFor="let option of filteredOptions | async" [value]="option">
## {{ option.name }}
## </mat-option>
## </mat-autocomplete>
## </mat-form-field>
## </form>
exemple de fichier ts:
this.filteredOptions = Observable<any[]>;
ngOnInit() {
this.filteredOptions = this.myControl.valueChanges
.pipe(
startWith({}),
map(getArrayOfValue(val))
);
}
// it is going to call an api to get the array of values to be shown in the field
getArrayOfValue(val): Observable<any[]> {
const url = this.ROOT_URL + 'veiculo/' + val;
return this.http.get<any[]>(url);
}
Ce code me donne une erreur
ERREUR dans src/app/oficina/cadastro/veiculo/veiculo.component.ts (55,5): erreur TS2322: le type "Observable>" n'est pas attribuable au type "Observable". Le type 'Observable' n'est pas assignable au type 'any []'. La propriété "comprend" est manquante dans le type "observable"
Je vois quelques problèmes, par exemple, vous devriez map(val => this.getArrayOfValue(val))
. Mais je suggérerais également quelques changements supplémentaires. Pensez à ajouter debounceTime
, distinctUntilChanged
et switchMap
. Définissez un temps de rebond de votre choix. Ceci, pour ne pas surcharger complètement l'API. De plus, switchMap est utile pour faire passer la requête à la dernière valeur saisie par l'utilisateur. Vous devriez également envisager d'utiliser un service pour vos demandes d'api, c'est généralement la façon dont nous traitons les choses. Je suggère donc de déplacer la requête http vers le service et d'appeler cela depuis le composant.
TS:
// inject your created service which makes the http-request
constructor(private service: Service) {
this.filteredOptions = this.myControl.valueChanges
.pipe(
startWith(''),
debounceTime(400),
distinctUntilChanged(),
switchMap(val => {
return this.filter(val || '')
})
);
}
// filter and return the values
filter(val: string): Observable<any[]> {
// call the service which makes the http-request
return this.service.getData()
.pipe(
map(response => response.filter(option => {
return option.name.toLowerCase().indexOf(val.toLowerCase()) === 0
}))
)
}
}
Le service appelle alors la requête http. Si vous ne surchargez pas l'API, nous pourrions stocker les données dans une variable après la première extraction, et retourner à la place un observable de cette variable, mais c'est juste facultatif.
opts = [];
getData() {
return this.opts.length ?
of(this.opts) :
this.http.get<any>('https://jsonplaceholder.typicode.com/users').pipe(tap(data => this.opts = data))
}
Vous semblez également utiliser value
pour votre option dans le modèle. Si vous souhaitez capturer l'intégralité de l'objet, utilisez [value]
.
Voici une DÉMO pour vous permettre de jouer avec :)