web-dev-qa-db-fra.com

Comment itérer à l'aide de la boucle ngFor Carte contenant la clé en tant que chaîne et les valeurs en tant qu'itération de la carte

Je suis nouveau sur angular 5 et j'essaie d'itérer la carte contenant une autre carte dans TypeScript. Comment itérer sous ce type de carte dans angular ci-dessous est le code pour le composant:

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

@Component({
  selector: 'app-map',
  templateUrl: './map.component.html',
  styleUrls: ['./map.component.css']
})
export class MapComponent implements OnInit {
  map = new Map<String, Map<String,String>>();
  map1 = new Map<String, String>();

  constructor() { 


  }

  ngOnInit() {
    this.map1.set("sss","sss");
    this.map1.set("aaa","sss");
    this.map1.set("sass","sss");
    this.map1.set("xxx","sss");
    this.map1.set("ss","sss");


    this.map1.forEach((value: string, key: string) => {
      console.log(key, value);

    });


    this.map.set("yoyoy",this.map1);

  }



}

et son template html est:

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


</ul>

<div>{{map.size}}</div>

runtime error

51
Feroz Siddiqui

Pour Angular 6.1 + , vous pouvez utiliser le canal par défaut keyvalue = ( Faites aussi la critique ):

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

WORKING DEMO


Pour la version précédente:

Une solution simple à cela est de convertir la carte en tableau: Array.from

Côté composant:

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());
}

Côté modèle:

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

WORKING DEMO

87
Vivek Doshi

Si vous utilisez Angular 6.1 ou version ultérieure, le moyen le plus pratique consiste à utiliser 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']]);
}
25
Londeren

Modifier

Pour angular 6.1 et versions ultérieures, utilisez le paramètre KeyValuePipe proposé par Londeren.

Pour angular 6.0 et plus ancien

Pour faciliter les choses, vous pouvez créer un tuyau.

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">

À l'état pur, il ne sera pas déclenché à chaque détection de changement, mais uniquement si la référence à la variable map change

démo de Stackblitz

19
David

En effet, map.keys() renvoie un itérateur. *ngFor peut fonctionner avec des itérateurs, mais la map.keys() sera appelée à chaque cycle de détection de changement, ce qui produira une nouvelle référence à la matrice, ce qui entraînera l'erreur que vous verrez. En passant, ce n'est pas toujours un erreur comme vous le pensez habituellement; il peut même ne pas endommager vos fonctionnalités, mais suggère que vous disposiez d'un modèle de données qui semble se comporter de façon insensée - évoluant plus rapidement que le détecteur de changement ne vérifie sa valeur.

Si vous ne voulez pas convertir la carte en tableau dans votre composant, vous pouvez utiliser le tuyau suggéré dans les commentaires. Il n'y a pas d'autre solution de contournement, semble-t-il.

P.S. Cette erreur ne sera pas affichée en mode de production, car elle ressemble plus à un avertissement très strict qu’à une erreur réelle, mais c’est quand même une bonne idée de ne pas le laisser.

6
Armen Vardanyan