2

// Updated along the discussion

I try to get JSON objects(Tasks) via http request and parse them into my own class to display them on my HTML page(Task Overwiew).

This is what I get:

enter image description here

This is the json array my php returns:

    {"result":[{"id":"3","znumber":"vor21423"},{"id":"2","znumber":"vor213"}]}

Here's my last try from the turtorial on angular.io. I've tested many answers but most of them relate to .json() which is no longer part of the HTML client.

export class ApiComponent {
 private apiUrl = 'http://localhost:81/work/get.php';

 results: Steve[];

 constructor(private http: HttpClient) {
 }

 ngOnInit() {
   this.getSteves();
 }

 getSteves() {
   this.http.get<ItemsResponse>(this.apiUrl)
      .subscribe(data => {
        this.results = data.result
          .map(steve => new Steve(steve.id, steve.zNumber));
            console.log(this.results);
            console.log(data);
      });
  }
}

The Interface

import { Steve } from './Steve';
export interface ItemsResponse {
  results: Steve[];
}

HTML

<div>
  <div *ngFor="let steve of results">
    <p> - {{steve.id}}</p>
    <p> - {{steve.zNumber}}</p>
  </div>
</div>

The Steve Class

export class Steve {
  public id = 0;
  public zNumber = '';

  constructor(id: number, zNumber: string) {
    this.id = id;
    this.zNumber = zNumber;
  }
}

The API

<?php 
require_once('db.php');

$sql = 'SELECT * FROM jobs ORDER BY id DESC';
$result = $conn->query($sql);
if ($result->num_rows > 0) {
    $data = array();
    while($row = $result->fetch_assoc()){
        $data[] = $row;
    }
    echo json_encode(array('result' => $data));
} else {
    echo 0;
}
?>
3
  • 1
    try inspecting the data object while debugging I believe you should use result not results. Commented Dec 4, 2017 at 10:44
  • I thougt that results is just an identifier for the json array. // 'steves' by now Commented Dec 4, 2017 at 10:48
  • The results is a variable and as such, can be named anyway you want. The conventions is to use singular, so result. It looks like data object coming from the server has no steves property. Commented Dec 4, 2017 at 10:49

2 Answers 2

2

First, you are not receiving an array, but an Object, so you need to get the array from the object result. Secondly, if you want to make the objects in the array instances of Steve, you need to explicitly tell Angular so.

You ItemsResponse actually looks like this (notice the result instead of results):

import { Steve } from './Steve';

export interface ItemsResponse {
  result: Steve[];
}

The request should show that you are getting response of type ItemsResponse.

 getSteves() {
   this.http.get<ItemsResponse>(this.apiUrl)
     .subscribe(data => {
       // your array is in 'result' object of your response
       this.results = data.result
         // create instances of your class
         .map(steve => new Steve(steve.id, steve.znumber))
     });
  }
Sign up to request clarification or add additional context in comments.

3 Comments

Okay thank you! The output now shows the id's but not the znumber string. Any idea why the znumber is undefined? // updated the screenshot.
Because znumber is coming from backend but you expect zNumber. Replace: ` .map(steve => new Steve(steve.id, steve.zNumber))` with: ` .map(steve => new Steve(steve.id, steve.znumber))`
i changed znumber to zNumber in my database. It Works. Thank you guys so much for the help :)
2

You are using Angular version 4 at least. In version 4 the Angular team decided to implicitly parse JSON results, so you wouldn't have to write JSON.parse(json.result) with each Ajax request.

In your example you replaced the value returned by server: result with steves and then you try to access it: data['steves'] but in the screenshot you can see that the values have already been extracted by Angular implicit JSON parsing and you are dealing with an array of objects.

So data['steves'], data['result'] etc. will always be undefined, cause the Angular HttpClient service, which replaced Http service in version 4 is already parsing JSON before it returns the data.

Just replace: this.results = data['steves']; with this.results = data; and everything will work.

11 Comments

You no longer have access to data['result'], since HttpClient parses it for you, removing result and assigning its value to data and then returning it. So the data that's returned is already an array you return from the server. There is no result, results, 'steves' and whatever else you had as the first property of your JSON when returning it from the backend. HttpClient already parsed it for you.
I can' just asign data to this.results . I get this error -> error TS2322: Type 'ItemsResponse' is not assignable to type 'Steve[]'. Property 'includes' is missing in type 'ItemsResponse'. data.results throws no error but gives me the same output as schown in the screenshots // updated the question to my current code
That's because of this line: this.http.get<ItemsResponse>(this.apiUrl) In essence you just told TS compiler that your return value is ItemsResponsewhich has results property and then you try to assign it to this.results of Steve[] type. So the interfaces are incompatible. Use this.http.get<Steve[]>(this.apiUrl) cause this is what you get back from the server - a list of Steves.
Cannot find a differ supporting object '[object Object]' of type 'object'. means that you try to iterate over object properties instead of array in *ngFor So if you have <div *ngFor="let steve of results"> in your template, results should be an array, not an object.
Thank you so far!! I dont get why angular think its an object. It is declared as Array, is it?
|

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.