Issue
I'm new to Angular and I'm trying to fetch a local api (localhost:4200/office_keys)
to show the items on an mat-autocomplete this way:
HTML:
<mat-form-field appearance="outline">
<mat-label>Office Key</mat-label>
<input matInput [formControl]="control" [matAutocomplete]="office_keys" #desc required />
<mat-autocomplete autoActiveFirstOption>
<mat-option *ngFor="let keys of office_keys" [value]="keys">
{{ keys }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
(part of) TS:
filteredOptions: Observable<any[]>;
office_keys: Observable<OfficeKey>;
saveForm: FormGroup;
control = new FormControl();
constructor(private officeKeyService: OfficeKeyService) {
}
this.saveForm = new FormGroup({
office_key: new FormControl("", [
Validators.required,
Validators.minLength(3),
Validators.maxLength(255),
]),
})
get office_key() {
return this.saveForm.get("office_key.description");
}
ngOnInit(): void {
this.filteredOptions = this.control.valueChanges.pipe(
startWith(""),
debounceTime(200),
distinctUntilChanged(),
switchMap((value) => this.filter(value || ""))
);
}
filter(val: string): Observable<any[]> {
return this.officeKeyService.read().pipe(
map((response) =>
response.filter((option) => {
return (
option.description.toLowerCase().indexOf(val.toLowerCase()) === 0
);
})
)
);
}
Service:
baseUrl = "http://localhost:8000/office_keys";
create(office_key: OfficeKey): Observable<OfficeKey> {
return this.http.post<OfficeKey>(this.baseUrl, office_key).pipe(
map((obj) => obj),
catchError((e) => this.errorHandler(e))
);
}
read(): Observable<OfficeKey[]> {
return this.http.get<OfficeKey[]>(this.baseUrl).pipe(
map((obj) => obj),
catchError((e) => this.errorHandler(e))
);
}
readById(id: number): Observable<OfficeKey> {
const url = `${this.baseUrl}/${id}`;
return this.http.get<OfficeKey>(url).pipe(
map((obj) => obj),
catchError((e) => this.errorHandler(e))
);
}
update(office_key: OfficeKey): Observable<OfficeKey> {
const url = `${this.baseUrl}/${office_key.id}`;
return this.http.put<OfficeKey>(url, office_key).pipe(
map((obj) => obj),
catchError((e) => this.errorHandler(e))
);
}
delete(id: number): Observable<OfficeKey> {
const url = `${this.baseUrl}/${id}`;
return this.http.delete<OfficeKey>(url).pipe(
map((obj) => obj),
catchError((e) => this.errorHandler(e))
);
}
But it is not working. I think I'm getting lost in the way Angular's architecture is built, how each thing connects and so on. What am I doing wrong in this specific case?
Solution
A mat-autocomplete has two parts: the input and the autoComplete itself. See that the "property" matAutocomplete
make reference to a "template reference variable", (the #auto="matAutocomplete") in the first example of the docs:
<input ... [matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete">
</mat-autocomplete>
Not make reference to an array, else to a "component" of type AutoComplete
The options of mat-autocomplete is like (again the example of the docs)
<mat-option *ngFor="let option of filteredOptions | async" [value]="option">
{{option}}
</mat-option>
See that it's used the pipe async. The pipe async work over an Observable. In general, this Observable is created using an Observable of the changes of the input. Here we have two options:
1.-use the operator map, to transform the value of the input in an array (filtering an array that we already loaded)
this.filteredOptions = this.myControl.valueChanges.pipe(
startWith(''),
map(value => this._filter(value)),
);
2.-Like you are trying to do using switchMap to return an observable -generally from a service-. but remember use the pipe async
Answered By - Eliseo
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.