How to iterate using ngFor loop Map containing key as string and values as map iteration

前端 未结 6 1587
孤独总比滥情好
孤独总比滥情好 2020-12-02 10:51

I am new to angular 5 and trying to iterate the map containing another map in typescript. How to iterate below this kind of map in angular below is code for component:

相关标签:
6条回答
  • 2020-12-02 11:18

    As people have mentioned in the comments keyvalue pipe does not retain the order of insertion (which is the primary purpose of Map).

    Anyhow, looks like if you have a Map object and want to preserve the order, the cleanest way to do so is entries() function:

    <ul>
        <li *ngFor="let item of map.entries()">
            <span>key: {{item[0]}}</span>
            <span>value: {{item[1]}}</span>
        </li>
    </ul>
    
    0 讨论(0)
  • 2020-12-02 11:19

    For Angular 6.1+ , you can use default pipe keyvalue ( Do review and upvote also ) :

    <ul>
        <li *ngFor="let recipient of map | keyvalue">
            {{recipient.key}} --> {{recipient.value}}
        </li>
    </ul>
    

    WORKING DEMO


    For the previous version :

    One simple solution to this is convert map to array : Array.from

    Component Side :

    map = new Map<String, String>();
    
    constructor(){
        this.map.set("sss","sss");
        this.map.set("aaa","sss");
        this.map.set("sass","sss");
        this.map.set("xxx","sss");
        this.map.set("ss","sss");
        this.map.forEach((value: string, key: string) => {
            console.log(key, value);
        });
    }
    
    getKeys(map){
        return Array.from(map.keys());
    }
    

    Template Side :

    <ul>
      <li *ngFor="let recipient of getKeys(map)">
        {{recipient}}
       </li>
    </ul>
    

    WORKING DEMO

    0 讨论(0)
  • 2020-12-02 11:27

    Edit

    For angular 6.1 and newer, use the KeyValuePipe as suggested by Londeren.

    For angular 6.0 and older

    To make things easier, you can create a pipe.

    import {Pipe, PipeTransform} from '@angular/core';
    
    @Pipe({name: 'getValues'})
    export class GetValuesPipe implements PipeTransform {
        transform(map: Map<any, any>): any[] {
            let ret = [];
    
            map.forEach((val, key) => {
                ret.push({
                    key: key,
                    val: val
                });
            });
    
            return ret;
        }
    }
    
     <li *ngFor="let recipient of map |getValues">
    

    As it it pure, it will not be triggered on every change detection, but only if the reference to the map variable changes

    Stackblitz demo

    0 讨论(0)
  • 2020-12-02 11:28

    If you are using Angular 6.1 or later, the most convenient way is to use KeyValuePipe

       @Component({
          selector: 'keyvalue-pipe',
          template: `<span>
            <p>Object</p>
            <div *ngFor="let item of object | keyvalue">
              {{item.key}}:{{item.value}}
            </div>
            <p>Map</p>
            <div *ngFor="let item of map | keyvalue">
              {{item.key}}:{{item.value}}
            </div>
          </span>`
        })
        export class KeyValuePipeComponent {
          object: Record<number, string> = {2: 'foo', 1: 'bar'};
          map = new Map([[2, 'foo'], [1, 'bar']]);
        }
    
    0 讨论(0)
  • 2020-12-02 11:28

    The below code useful to display in the map insertion order.

    <ul>
        <li *ngFor="let recipient of map | keyvalue: asIsOrder">
            {{recipient.key}} --> {{recipient.value}}
        </li>
    </ul>
    

    .ts file add the below code.

    asIsOrder(a, b) {
        return 1;
    }
    
    0 讨论(0)
  • 2020-12-02 11:33

    This is because map.keys() returns an iterator. *ngFor can work with iterators, but the map.keys() will be called on every change detection cycle, thus producing a new reference to the array, resulting in the error you see. By the way, this is not always an error as you would traditionally think of it; it may even not break any of your functionality, but suggests that you have a data model which seems to behave in an insane way - changing faster than the change detector checks its value.

    If you do no want to convert the map to an array in your component, you may use the pipe suggested in the comments. There is no other workaround, as it seems.

    P.S. This error will not be shown in the production mode, as it is more like a very strict warning, rather than an actual error, but still, this is not a good idea to leave it be.

    0 讨论(0)
提交回复
热议问题