Displaying dynamic key-value pairs in each row of an Angular mat-table

I need help displaying a key-value pair data in JSON format dynamically within a table using Angular mat-table. The keys will vary, so there is no set list of keys that will be included in the JSON. This is an example of the data:

var data = {
 "cars" : 24,
 "fruit" : "apple",
 "phone" : "Iphone",
 "food" : "Burger"
};

The desired table output should have:

  • Table header with columns for KEY and VALUE
  • Each row showing the dynamic key value from the JSON object

Expected final table structure can be seen here:

https://i.stack.imgur.com/nHZTK.png

Answer №1

Converting an object to an array

  dataSource = [];
  var data = {
    cars: 24,
    fruit: "apple",
    phone: "Iphone",
    food: "Burger"
  };

  for (const key in data) {
    dataSource.push({ key, value: data[key] });
  }

and utilizing it with Angular Material

.ts file

import { Component } from "@angular/core";
export interface RowElement {
  key: string;
  value: string;
}
@Component({
  selector: "table-basic-example",
  styleUrls: ["table-basic-example.css"],
  templateUrl: "table-basic-example.html"
})
export class TableBasicExample {
  data = {
    cars: 24,
    fruit: "apple",
    phone: "Iphone",
    food: "Burger"
  };

  displayedColumns: string[] = ["key", "value"];
  dataSource: RowElement[];

  constructor() {
    for (const key in this.data) {
      this.dataSource.push({ key, value: this.data[key] });
    }
  }
}

.html file

<table mat-table [dataSource]="dataSource">
  <!-- Key Column -->
  <ng-container matColumnDef="key">
    <th mat-header-cell *matHeaderCellDef>Key</th>
    <td mat-cell *matCellDef="let element">{{element.key}}</td>
  </ng-container>

  <!-- Value Column -->
  <ng-container matColumnDef="value">
    <th mat-header-cell *matHeaderCellDef>Value</th>
    <td mat-cell *matCellDef="let element">{{element.value}}</td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

Answer №2

No need to convert the object into an array; you can simply utilize the keyvalue pipe.

In your Typescript file:

// Class properties
displayedColumns: string[] = ['key', 'value'];
dataSource = data;

// Use this method to maintain the order of object properties
public orderByKey(a, b) {
    return a.key;
}

In your HTML file:

<table mat-table [dataSource]="dataSource | keyvalue:orderByKey" class="mat-elevation-z8">
  <ng-container matColumnDef="key">
    <th mat-header-cell *matHeaderCellDef> Key </th>
    <td mat-cell *matCellDef="let element"> {{element.key}} </td>
  </ng-container>

  <ng-container matColumnDef="value">
    <th mat-header-cell *matHeaderCellDef> Value </th>
    <td mat-cell *matCellDef="let element"> {{element.value}} </td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

You can see this in action on this StackBlitz link

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Retrieving specific properties from a JSON object and logging them

I am attempting to access JSON Object properties directly and log them using the following function : loadProcesses(filter?){ this._postService.getAllProcess(filter) .subscribe( res=> { this.processListe = res; // console.log(this.p ...

Placeholder variable not specified in radio buttons

I am currently facing challenges applying validations to radio buttons in Angular. Normally, I create a #templateRefVariable on the input for other input types, which allows me to access the NgControl and use properties like touched. My goal is to set the ...

Error: The property 'children' is not found in type '{ children?: ReactNode; }'

I have been working on implementing the search bar feature from the provided link. Despite my efforts to match the types correctly, I keep encountering a TypeScript error. Homepage.tsx const [searchQuery, setSearchQuery] = useState(query || '' ...

defining data types based on specific conditions within an object {typescript}

Can someone help with implementing conditional function typing in an object? let obj = { function myfunc (input: string): number; function myfunc (input: number): string; myfunc: function (input: string|number):string|number { ... } } I've been ...

Storing information in a FormArray within an Angular reactive form

I'm facing a challenge with setting an array of data from an API to a FormGroup that contains a form array. It seems like I'm missing something in the process. Form this.blog = this.fb.group({ title: ['', Validators.required], ...

Module error caused by Typescript path inconsistency

After creating a new model named "project" within the existing project, I encountered an error when attempting to import the class into another typescript file in VS2019. The specific error message thrown is as follows: "ts2307 cannot find module ' ...

What are some ways to detect TypeScript type errors in the data of a Vue component?

Recently, I delved into Typescript development using Nuxt-ts and Vue 2. My goal was to steer clear of class-style components so I opted for the following approach. I created my Interfaces in a folder named /types. Whenever I needed to declare a type in a ...

Styling array of arrays

When retrieving data from an API, the structure looks like this: "key1" : { "subkey1" : value "subkey2" : value "subkey3" : value } "key2" : { &q ...

What sets apart Object.assign {} from Object.assign []?

While reviewing code done by a previous developer who is no longer with us, I observed that they sometimes used Object.assign({}, xyz) and other times they used Object.assign([], abc); Could there be a distinction between the two methods? ...

Error in TypeScript when utilizing an Enum as a string

Attempting to include a string enum in my Angular 2 project resulted in an error during the npm project startup: ERROR in e:/projects/dbtool-fullstack/dbtool-client/src/app/shared/models/full-m odels/enums/Sex.ts (2,10): Type '"Male"' is not ass ...

What is the reason behind Angular's renderer.listen() causing the text to be deselected?

(Background: my project involves developing an email processor that displays emails on a web page) To enable click events in a specific area, I leverage Angular's Renderer2. This approach is necessary because the content is dynamically generated with ...

Exploring the sharing of observables/subjects in Angular 2

UPDATE: After further investigation, it appears that the SharedService is being initialized twice. It seems like I may be working with separate instances, causing the .subscribe() method to only apply to the initiator. I'm not sure how to resolve this ...

The type '(props: Props) => Element' cannot be assigned to the type 'FunctionComponent<FieldRenderProps<any, HTMLElement>>' in React-final-form

I'm fairly new to using TypeScript, and I am currently working on developing a signUp form with the help of React-Final-Form along with TypeScript. Here is the code snippet that describes my form: import React from "react"; import Button from "@mater ...

Effective strategies for managing form submissions with React and Typescript

As I dive into refactoring my code to TypeScript, especially as I am still getting accustomed to it, I find myself pondering about the HTML element types with React events. This has led me to rethink how I approach form creation and submission event handli ...

Exploring the use of Jest for testing delete actions with Redux

I've been working on testing my React + Redux application, specifically trying to figure out how to test my reducer that removes an object from the global state with a click. Here's the code for my reducer: const PeopleReducer = (state:any = init ...

What is the best way to retrieve a specific field from the observable data stream?

When working with observables, I often find myself using them like this: ... const id = 1337; this.service.getThing(id).subscribe( suc => doSomething(suc.name), err = doSomethingElse() ); Lately, I've been utilizing the async pipe more freque ...

What is the process for injecting dependencies in a custom Angular class?

I am facing an issue with my Angular service setup: @Injectable({ providedIn: 'root', }) export class Services { public service1 = new Service1(); } The Service1 class looks like this: export class Service1 { public http: HttpRequ ...

The tsconfig.json file is not effectively excluding the node_modules folder

When attempting to compile my project using the command npm run ng build, I encounter errors originating from the node_modules folder, as dictated by the rules in tsconfig.json. node_modules/@alfresco/js-api/src/api/gs-core-rest-api/model/filePlan.ts:46:1 ...

Add the onclick() functionality to a personalized Angular 4 directive

I'm facing an issue with accessing the style of a button in my directive. I want to add a margin-left property to the button using an onclick() function in the directive. However, it doesn't seem to be working. Strangely, setting the CSS from the ...

Turning off @Output as Observable: A step-by-step guide

I have a query regarding unsubscribing Outputs in Angular. While I am aware that EventEmitter is automatically cleaned up, there was a time when I needed to use an Observable as my Output. Specifically, I wanted to take an Output that emitted events at mos ...