0

In Angular, I want to convert a JSON array to an HTML table.

I have seen an old answer for AngularJS:

<table>
    <thead>
      <tr>
        <th ng-repeat="(key, value) in records[0]">{{key}}</th>
      </tr>
    </thead>
    <tbody>
      <tr ng-repeat="(key, value) in records">
        <td ng-repeat="(key, value) in value">
          {{value}}
        </td>
      </tr>
    </tbody>
</table>

JSON looks like this:

[{
    "Name": "Alfreds Futterkiste",
    "City": "Berlin",
    "Country": "Germany"
}, {
    "Name": "Berglunds snabbköp",
    "City": "Luleå",
    "Country": "Sweden"
}, {
    "Name": "Centro comercial Moctezuma",
    "City": "México D.F.",
    "Country": "Mexico"
}]

I've tried to translate it to the Angular syntax. Here is what I got so far:

<table>
    <thead>
      <tr>
        <th *ngFor="let item of records[0]  | keyvalue">{{item.key}}</th>
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="let item of records">
        <td *ngFor="let item1 of item | keyvalue">
          {{item1.value}}
        </td>
      </tr>
    </tbody>
</table>

Right now it's failing to compile because records[0] is undefined... how can I translate this expression to the newer syntax (or create something equivalent)?

UPDATE 1:

I have a partial solution. However with this partial solution the rendered table is not completely identical to the older AngularJS rendition (because it creates multiple unnecessary header rows, which only one of them is populated, as opposed to only one header row in the older rendition).

<table style="border-collapse: collapse;">
    <thead *ngFor="let item of records; let last=last">
      <tr *ngIf="last">
        <th *ngFor="let item1 of item | keyvalue">
          {{item1.key}}
        </th>
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="let item of records">
        <td *ngFor="let item1 of item | keyvalue">
          {{item1.value}}
        </td>
      </tr>
    </tbody>
</table>

Do you have a better way to do it, possibly similar to the older AngularJS version?

UPDATE 2:

In Angular, I access the JSON data through a request from Angular that is then redirected to a back end service. That service may read a file, or get the data from a database. When the back end service has the data ready, it returns the data to the Angular request. The code on the Angular end looks like this:

  HTML:

  <div>
    <h3>Test Post Request</h3>
    <button (click)="postData()">Click Me</button>
    <div>Response: {{records}}</div>
  </div>

  TypeScript:

  private dataPostTestUrl = '/api/postTest';
  records: string | undefined;

  public postData(): void {
    this.appService.sendData().subscribe((data: any) => {
      this.records = data.content;
    });
  }

  public sendData(): Observable<any> {
    return this.http.post(this.dataPostTestUrl, {});
  }
6
  • Hard to tell from the provided info but you might be rendering before the API call returns. Try adding *ngIf=“records” to the table tag. Commented May 13, 2022 at 11:20
  • @TheHeadRush No. Commented May 13, 2022 at 11:29
  • More info needed. Would be good to see component code around how you fetch the data. Commented May 13, 2022 at 11:40
  • @TheHeadRush The syntax you suggest is not valid. Anyway, records does have all the JSON data at this point. It's just that records[0] might not be valid syntax there for some reason. Commented May 13, 2022 at 11:42
  • How do you import the JSON into the component? Commented May 13, 2022 at 11:53

2 Answers 2

0

I think maybe you need to define records in the component.

records = [{
    "Name": "Alfreds Futterkiste",
    "City": "Berlin",
    "Country": "Germany"
}, {
    "Name": "Berglunds snabbköp",
    "City": "Luleå",
    "Country": "Sweden"
}, {
    "Name": "Centro comercial Moctezuma",
    "City": "México D.F.",
    "Country": "Mexico"
}];
Sign up to request clarification or add additional context in comments.

1 Comment

Hmmm... think again.
0

I am fairly certain this is what you need: https://stackblitz.com/edit/angular-ivy-n7irpw?file=src/app/hello.component.ts

Take a look at how I import the file in the app.component.ts As well as how I loop in the HTML.

Let me know if it helps!

6 Comments

Can you explain my update?
I'd need a replication of the issue to have a better look. As of now, my best guess is that your record[0] does not return the proper data. Please make a minimal reproduction scenario and I will take a look.
I will try to do it. Also, I noticed that in your code the columns (fields) were printed in an alphabetic order (from left to right). Is it possible to print them in the order they appear in the JSON file (i.e. name, city, country)?
It is possible you just need to tweak the key-value pipe as it orders them alphabetically. See the Angular docs: angular.io/api/common/KeyValuePipe
I was not able to make my demo project run on stackblitz... it's stuck... (I guess after 5 years they are still a work in progress). But I provided more details in my "Update 2" above. Please take a look. It seems like when I invoke the postData() function (by a button), records already has all the data when the html rendition starts. Is it not what .subscribe((data) => ...) supposed to do? Also pay attention that it is a compilation error. I see nothing because the project doesn't compile. It's not (yet) a runtime problem of reading a Future that has not completed yet its course.
|

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.