Iterating Over Objects in Angular with *ngFor: Accessing Keys and Values

Introduction

When working with data structures in web applications, it’s common to encounter scenarios where you need to render lists based on objects. In Angular, this can be accomplished by iterating over an object using the *ngFor directive. Unlike AngularJS (1.x), which had a built-in syntax for iterating over key-value pairs directly within directives like ng-repeat, Angular (2+) requires different approaches. This tutorial explores methods to access and iterate over keys and values of objects in Angular templates, leveraging both built-in pipes and custom solutions.

Understanding the Challenge

In Angular, when dealing with objects, we often need to display their key-value pairs dynamically in the template. The challenge lies in converting an object into a list format that can be consumed by *ngFor. In older versions of Angular, developers had to manually convert objects or use custom pipes to achieve this functionality.

Using Built-in KeyValue Pipe (Angular 6+)

Starting from Angular version 6.1, the framework introduced a built-in pipe called keyvalue in the @angular/common package. This pipe is specifically designed for iterating over objects and maps within templates.

Example Usage

<div *ngFor="let item of demo | keyvalue">
    Key: <b>{{item.key}}</b> - Value: <b>{{item.value}}</b>
</div>

In this example, demo is an object:

demo = {
  'key1': [{'key11':'value11'}, {'key12':'value12'}],
  'key2': [{'key21':'value21'}, {'key22':'value22'}]
};

The keyvalue pipe transforms the object into an array of objects, each containing a key and a value, which can be accessed directly in the template.

Keeping Original Order

If maintaining the original order of properties is essential, you can use the keyvalue:onCompare variant. You need to define a comparison function in your component:

import { KeyValue } from '@angular/common';

@Component({
  /* ... */
})
export class MyComponent {
  onCompare(_left: KeyValue<any, any>, _right: KeyValue<any, any>): number {
    return -1; // Maintain original order
  }
}

Custom Pipe for Unsorted Iteration

If you prefer not to sort the key-value pairs and want more control over the iteration process, creating a custom pipe is an effective solution. This method allows iterating over objects while preserving their insertion order.

Custom KeyValuePipe

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ name: 'keyValueUnsorted', pure: false })
export class KeyValuePipe implements PipeTransform {
  transform(input: any): any {
    let keys = [];
    for (let key in input) {
      if (input.hasOwnProperty(key)) {
        keys.push({ key, value: input[key] });
      }
    }
    return keys;
  }
}

This pipe iterates over the object properties and returns an array of objects containing key and value. Setting pure: false ensures that the pipe is evaluated on every change detection cycle, accommodating dynamic changes in the object’s structure.

Using the Custom Pipe

<div *ngFor="let item of demo | keyValueUnsorted">
    Key: <b>{{item.key}}</b> - Value: <b>{{item.value}}</b>
</div>

Alternative Approach with Object.keys

If you’re using Angular versions before 6.1 or prefer not to use pipes, another approach is leveraging JavaScript’s Object.keys method in your component:

Using Object Keys in Templates

import { Component } from '@angular/core';

@Component({
  selector: 'app-myview',
  template: `
    <div *ngFor="let key of objectKeys(demo)">
      {{key}} : {{demo[key]}}
    </div>
  `,
})
export class MyComponent {
  objectKeys = Object.keys;
  demo = { 
    'key1': [{'key11':'value11'}, {'key12':'value12'}],
    'key2': [{'key21':'value21'}, {'key22':'value22'}]
  };
}

Here, Object.keys is used to convert the object into an array of keys, which can then be iterated over using *ngFor.

Conclusion

Accessing and iterating over objects in Angular templates requires converting these structures into iterable formats like arrays. By utilizing built-in pipes like keyvalue, custom pipes for specific needs, or JavaScript methods such as Object.keys, developers can efficiently display key-value pairs from objects within their applications. These techniques offer flexibility depending on the version of Angular being used and specific project requirements.

Leave a Reply

Your email address will not be published. Required fields are marked *