2

I have a service API that pulls data from Django-REST. The returned JSON looks like:

[
{
    "manufacturer": "Mfg",
    "model": "Model",
},
{
    "manufacturer": "Mfg2",
    "model": "Model2",
}
]

The service API function getData returns:

return this.httpClient.get(`${this.apiURL}/data/`);

Note I am using ListAPIView in Django, and I have verified that the above URL returns the JSON object shown above (though I have to add ?format=json to get the raw data outside of Django's APIView).

I then have an angular component that calls the service API function to convert the observable to an array of objects:

export class Data implements OnInit {

private records = Array<object> = [];

...

constructor(private  apiService:  ApiService) {}

ngOnInit() {
  this.getData();
}

public getData() {
 this.apiService.getData().subscribe((data: Array<object>) => {this.records = data});

There are no error or warnings, but in the component's HTML file when I try to access the record array it always has a length of 0. For example, the following will print "0" and an empty table.

<P> {{ records.length }}</P>
<table>
  <tr>
    <th>Manufacturer</th>
  </tr>
  <tr *ngFor="let record of records">
    <td> {{ record.manufacturer }} </td>
  </tr>
</table>

What am I missing?

3
  • I think the problem is that you are trying to assign data into objects without parsing. Can you provide a demo? Commented Feb 11, 2019 at 7:47
  • parse your data using JSON.parse(data), if its stringified from the server side. Commented Feb 11, 2019 at 7:49
  • don't assign Array<object> = [] into your records variable just declare it and it will be work Commented Feb 11, 2019 at 8:49

2 Answers 2

5

If you define a model using an interface, and then use that interface as a generic parameter to the get call, the HttpClient will automatically map the response to the defined structure.

For example:

Interface

export interface Product {
  manufacturer: string;
  model: string;
}

Data Service

return this.httpClient.get<Product[]>(`${this.apiURL}/data/`);

Component

private records: Product[];

public getData() {
 this.apiService.getData().subscribe((data: Product[]) => this.records = data);
}

EDIT: If you want to add a console.log to the above, you need to add it like this:

public getData() {
 this.apiService.getData().subscribe((data: Product[]) => {
     this.records = data;
     console.log(this.records);
  );
}

Template

<div *ngIf="records">
 <p> {{ records.length }}</p>
 ...
</div>

When the template first appears, the async data retrieval process may not yet have finished. So by putting an ngIf around the page, it won't attempt to display the elements until the data is retrieved.

Sign up to request clarification or add additional context in comments.

2 Comments

Hello , when i console log in ` this.apiService.getData().subscribe((data: Product[]) => this.records = data); ` , then it still in Object type not in Product[] type and it is not workin. Can you please update answer . Thankk you
See the edit above.
0

you need to add the async pipe to it.

<tr *ngFor="let record of records|async">
    <td> {{ record.manufacturer }} </td>
  </tr>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.