Angular 6: get array of objects from corresponding JSON through httpClient

13,940

I believe it's because this.rows = result is not wrapped in {}. Can you log out your subscription to make sure it's actually coming back?

dataService.getData()
.subscribe(
  (result: Array<DataObject>) => { 
    console.log('success', result);
    this.rows = result
  },
  (error: any) => { 
    console.log('error', error);
  }
)

I would also suggest moving that call to NgOnInit rather than the constructor.

Share:
13,940
Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    Admin almost 2 years

    I'm trying to populate a table with data from my backend API. The table expects a rows input that's an array of objects, with each object representing a row in the table and consisting of column-name/value pairs. The backend posts an array of JSON objects like this:

    [{"column1":"val1","column2":"val2"},{"column1":"valA","column2":"valB"}]

    If I just copy and paste that string into my .ts file and assign it directly to the rows property, everything works correctly:

    this.rows = [{"column1":"val1","column2":"val2"},{"column1":"valA","column2":"valB"}]
    

    This works regardless of whether the rows property is defined as any or Array<DataObject> or anything in between. So why can't I seem to achieve the same functionality through httpClient?

    Here's what I have so far:

    data-service.service.ts:

    @Injectable()
    export class DataService {
    
        constructor (private http: HttpClient) {}
    
        public getData() {
            return this.http.get<Array<DataObject>>(apiURL, {responseType : 'json'});
        }
    

    table-view.route.ts:

    export class TableView implements OnInit {
    
        rows: Array<DataObject>;
    
        constructor(dataService: DataService) {
            dataService.getData()
                       .subscribe((result: Array<DataObject>) => this.rows = result)
        }
    }
    

    data-object.ts

    export interface DataObject {
        column1: string;
        column2: string;
    }
    

    This seems to be correctly fetching the data, but it's typed wrong or wrapped in an extra object or something and the table can't read it. No errors; just empty table. Interestingly, I added this to my html before the table declaration just to make sure my data was getting through:

    <div>{{rows[0].column1}}</div>
    

    This correctly outputs "val1", AND it suddenly populates the table with ALL the data. Does this access somehow change the type of rows into something the table component can understand?

    I've tried all sorts of variations of the above code with and without type-checking; I've tried removing the json content header, reading it as plaintext, then using JSON.parse(). I realize that I could just iterate through the array, instantiating DataObjects and mapping the fields individually before pushing them to rows, but there has to be a simpler way to do this, right...? Any push in the right direction would be appreciated.

  • Admin
    Admin almost 6 years
    Good call on the logging; turns out the Table View route is correctly decoding the objects from the subscription after all. The problem is that the Table component itself gets initialized before that happens, so the rows input is empty. Using the table's search/sort features seems to recheck the input and then everything appears correctly. I'm gonna play around with it. This response timing stuff seems pretty fundamental. Any suggestions for articles/tutorials to brush up on it?
  • Admin
    Admin almost 6 years
    Note: I just wrapped the table component in a div with *ngIf="rows" and that solved it completely.