Paintbox
Paintbox

Reputation: 407

Populate dropdown from observable

I try to fill an array with values provinding from one service.

The array must fill a dropdown. I follow this post.

The array is defined like this : dropdownList: Array<{id: number, description: string}>;

The service method's is :

async loadFoodTypes(){
    const api: string =  environment.apiAddress + 'FoodType';
    await this.httpClient.get<FoodType[]>(api)
    .pipe()
    .toPromise()
    .then((response: FoodType[]) => {
      this._foodType.next(response);
    })
    .catch(err => console.log(err))
  } 

The FoodType type is defined like this:

 id?: number;
    description: string;
    shortDescription: string;

When I call the service I try to fill array with data.

loadFoodTypes(){
    this.foodtypesService.loadFoodTypes().then(response => 
      this.dropdownList.push({id: <number>(<unknown>response as FoodType).id, description: (<unknown>response as FoodType).description})
    );
  }

My problem is that I have these 2 error messages in the browser console :

Error: Uncaught (in promise): TypeError: Cannot read properties of undefined (reading 'id')

and

Uncaught (in promise): TypeError: Cannot read properties of undefined (reading 'push')

I presume the second one is linked to the first one.

Thanks for your help.

Upvotes: 0

Views: 868

Answers (2)

pemibo
pemibo

Reputation: 73

You're not returning anything from loadFoodTypes(). That's why

this.foodtypesService.loadFoodTypes().then(response => 

isn't working. Your response is undefined.

The way that's "more Angular" would be something like

  • In the service:
loadFoodTypes(): void {
    const api: string =  environment.apiAddress + 'FoodType';
    this.httpClient.get<FoodType[]>(api)
    .subscribe(response => this._foodType.next(response))
  } 

...

getFoodTypes(): Observable<FoodType[]> {
   return this._foodType.asObservable();
}

  • In the component:
loadFoodTypes(){
    this.foodtypesService.getFoodTypes()
        .subscribe(foodTypes => 
         this.dropdownList = foodTypes.map((foodType: FoodType) => ({id: foodType.id, description: foodType.description})
        );
  }

And don't forget to unsubscribe from your observables.

Upvotes: 2

Raz Luvaton
Raz Luvaton

Reputation: 3770

The problem is that you don't return the data in the load food type function,

async loadFoodTypes(){
    const api: string =  environment.apiAddress + 'FoodType';
    await this.httpClient.get<FoodType[]>(api)
    .pipe()
    .toPromise()
    .then((response: FoodType[]) => {
      this._foodType.next(response);
      return response;
    })
    .catch(err => console.log(err))
  } 

Also, the code in the catch don't rethrow the error so it will return undefined in the next .then


General notes on your code:

  1. You can remove the .pipe as it
  2. Don't use .toPromise as it deprecated

Upvotes: 1

Related Questions