Issue
I am trying to use Autocomplete from Angular Material.
Their data is options: string[] = ['One', 'Two', 'Three'];
, but instead of that I have an object.
This is how I get the data from the object, which is in currencies.json:
list(): Observable<Currencies> {
return this._http.get('./assets/currencies.json') as unknown as Observable<Currencies>;
}
public currencies$ = this.getAllCurrencies();
getAllCurrencies(): Observable<Currencies> {
return this._currencyService.list();
}
Now this is how I tried to bind the autocomplete:
<ng-container *ngIf="currencies$ | async">
<mat-form-field appearance="fill">
<mat-label>Currency</mat-label>
<input id="currency" type="text" matInput placeholder="Select a currency. E.g. USD" [matAutocomplete]="auto" formControlName="currency">
<mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
<mat-option *ngFor="let currency of currencies$ | keyvalue" [value]="currency.key">
{{currency.key}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</ng-container>
this.currencies$ = this.formMain.valueChanges.pipe(
startWith(''),
map(value => this.currencies$.subscribe(data => data.currency.includes((value.toString().toUpperCase() || '')))),
);
But then I get this error:
TS2322: Type 'Observable' is not assignable to type 'Observable'. Property 'currency' is missing in type 'Subscription' but required in type 'Currencies'.
How can I fix this?
I have also tried it this way:
currencies?: Observable<string[]>;
this.currencies = this.formMain.valueChanges.pipe(
startWith(''),
map(value => this.currencies$.subscribe(data => data.currency.includes((value.toString().toUpperCase() || '')))),
);
but then I get this error:
TS2322: Type 'Observable' is not assignable to type 'Observable<string[]>'. Type 'Subscription' is missing the following properties from type 'string[]': length, pop, push, concat, and 28 more.
Also tried it without subscribe()
:
this.formMain.valueChanges.pipe(
startWith(''),
map(value => [this.currencies$].filter(currency => currency.includes(value)))
);
But then I get the error:
TS2339: Property 'includes' does not exist on type 'Observable'.
This is my code on StackBlitz and this is the official code of Angular Material on StackBlitz. I want the result to be exactly the same as the official code but with my own data.
Solution
First of all, you use wrong interface for your object.
The code
export interface Currencies {
currency: string;
}
means that your data should be smth like:
{
currency: 'some string'
}
In case of your object you can use:
export type Currencies = Record<string, string>;
Secondly, you don't have to cast your http call:
this._http.get('./assets/currencies.json') as unknown as Observable<Currencies>;
just use generic version of http.get<T>
method:
this._http.get<Currencies>('./assets/currencies.json')
^^^^^^^^^^
Third, you should be using [formControl]
binding in your stackblitz because you don't have a wrapper with formGroup
:
formControlName="currency" => [formControl]="myControl"
Finally, while constructing currencies$
observable you need to continue work with Observable
by using switchMap
instead of map
rxjs operator:
currencies$ = this._currencyService.list().pipe(
switchMap((currencies) => {
return this.myControl.valueChanges.pipe(
startWith(''),
map((query) =>
Object.fromEntries(
Object.entries(currencies).filter(([key]) =>
key.includes(query.toUpperCase())
)
)
)
);
})
);
Answered By - yurzui
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.