Search code examples
angulartypescriptangular-httpclient

Angular http.get() returns array with data


I have a service:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Color } from '../model/color';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class ColorService {
  private productsUrl = 'http://localhost:5500/colors/';

  constructor(private http: HttpClient) { }

  getColors(): Observable<Color[]> {
    var colors = this.http.get<Color[]>(this.productsUrl + "all");
    
    return colors;
  }
}

and a component that gets the result of this method:

ngOnInit(): void {
  this.colorsService.getColors()
      .subscribe((colors) => {
        this.colors = Object.values(colors);
        this.colors.sort((a,b) => a.name.localeCompare(b.name));
        console.log(colors);
      }, err => {
        this.displaySpinner = false;
      }, () => {
        this.displaySpinner = false;
      });
}

My Color interface looks like this:

export interface Color {
    id: number;
    number: string;
    name: string;
    imagePath: string;
    category: string;
    color: string;
    brand: string;
}

Now when I do this console.log in the component, it gives me an array named colors, with as a child another array with the actual data:

{
  colors: [
    {
      id: 1,
      number: 159,
      name: 'glamorous peach',
      imagePath: '/src/assets/img/colors/color104.jpeg',
      category: 'summer',
      color: 'orange',
      brand: 'Pink Gellac'
    }
  ]
}

I seem to recall that this was not the case in a previous version of angular, and when I do something like the below in the HTML page, it is unable to get the color.name, I think because of the array nesting happening here:

<mat-grid-tile *ngFor="let color of colors">
    <mat-card class="example-card"
        style="width: 95%; border-radius:15px; box-shadow: 4px 4px 6px -1px rgba(0,0,0,0.15);">
        <mat-card-content>
            <mat-grid-list cols="1" rowHeight="250">
                <mat-grid-tile class="tile" style="overflow:auto;">
                  <div class="wrapper">
                    <p>{{color.name}}</p>
                  </div>
                </mat-grid-tile>
              </mat-grid-list>
        </mat-card-content>
    </mat-card>
</mat-grid-tile>

Any idea of how to work around this? Because of the typing in the service (Color[]), I seem to be unable to manipulate this array into what I need for the ngFor to work.


Solution

  • The structure is coming from the API, you just need to set it differently for it to work! Access the colors array and set it to the variable!

    ngOnInit(): void {
        this.colorsService.getColors()
            .subscribe((response: any) => {
              console.log(response);
              this.colors = <Array<Color>>response.colors;
              this.colors.sort((a,b) => a.name.localeCompare(b.name));
            }, err => {
              this.displaySpinner = false;
            }, () => {
              this.displaySpinner = false;
            });
      }