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>
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>
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>
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']]);
}
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
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.