简体   繁体   中英

Angular Observable object access

I am current learning and getting used to Angular, and while getting information from an Observable I am unable to get it out of object form.

public rowData$!: Observable<any[]>;

UpdateGrid() {
  this.rowData$ = this.http
    .get<any[]>('http://localhost:8080/data');
    this.rowData$.forEach(value => console.log(value));
}

This console log gives me the proper http response:

(2) [{…}, {…}]
 0: {id: 1, name: 'Bob', sex: 'Male'}
 1: {id: 2, name: 'Susan', sex: 'Female'}
length: 2
[[Prototype]]: Array(0)

My tries of using mapping and other ways of extracting the data have failed, and each time I just get Object object whenever the extraction is displayed in html.

Is there an easy way to pull out the data? Any help is appreciated, I can't seem to find an answer online and the docs give examples that I haven't been able to get working. Thank you.

These are basically two questions in one. How to print the array as a string inside your template (which I suppose you only need for debugging purposes) and how to transform the array before passing it to ag-grid. Let's try to answer these in order.

How to print Observable data on the template

When binding to the content of your HTML using the interpolation syntax ( {{ }} ), angular calls the toString() method under the hood if the object to be bound is not a primitive. This means, getting an output [object Object] is what the bound object's toString() method returns - and is the default for all objects if not implemented otherwise. For arrays, the implementation is overwritten and usually returns the values inside the array joined by a comma and if the array elements are objects themselves, it calls the toString() function on those. This leads to the behaviour you are observing.

This means you have to either override the toString() method for the inner objects, or stringify the value yourself. Angular provides the | json | json pipe which does this stringification for you using the JSON.stringify() method under the hood.

Using your data as an example, these are the outputs you'd be seeing:

<!-- This prints "[object Object]" since an Observable is an Object -->
{{ rowData$ }} 

<!-- This prints "[object Object],[object Object]" since the array contains two Objects -->
{{ rowData$ | async }}

<!-- 
This prints
[ {id: 1, name: 'Bob', sex: 'Male'}, {id: 2, name: 'Susan', sex: 'Female'} ] 
since the json pipe handles the stringification for us
-->
{{ rowData$ | async | json }}
How to transform the data

Since you did not provide what format you want the data in, I'll show you where you can put transformation logic with observables in general.

Each observable has a .pipe() function which takes operators you can apply to the stream to transform it. The operator you need is the map operator, since you want to transform each received value (in your case: the whole array) into a different value (in your case: a new array containing different looking objects).

import { map } from 'rxjs/operators'; // <-- import the operator

@Component({ /* omitted */ })
export class MyComponent {
  public rowData$!: Observable<any[]>; // digression: Try to avoid any, it removes typesafety

  updateGrid() { // digression: Use lower camel case for method names, it's a convention :)
    this.rowData$ = this.http
      .get<any[]>('http://localhost:8080/data')
      .pipe(
        map(rowData => // <-- use the map operator here, it takes each value and returns a new one
          rowData.map(entry => { // <-- map each object in your array
            // return a new entry in the format you need
          }); 
        ) 
      );
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM