Jestem nowy w Angular 5 i próbuję iterować mapę zawierającą inną mapę w maszynopisie. Jak iterować poniżej tego rodzaju mapy w układzie kątowym poniżej jest kod dla komponentu:
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);
}
}
a jego szablon html to:
<ul>
<li *ngFor="let recipient of map.keys()">
{{recipient}}
</li>
</ul>
<div>{{map.size}}</div>
javascript
angular
typescript
angular-cli
Feroz Siddiqui
źródło
źródło
Odpowiedzi:
Dla Angular 6.1+ możesz użyć domyślnego potoku
keyvalue
( wykonaj przegląd i głosuj za ):<ul> <li *ngFor="let recipient of map | keyvalue"> {{recipient.key}} --> {{recipient.value}} </li> </ul>
PRACY DEMO
W przypadku poprzedniej wersji:
Jednym prostym rozwiązaniem jest przekonwertowanie mapy na tablicę: Array.from
Strona komponentu:
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()); }
Strona szablonu:
<ul> <li *ngFor="let recipient of getKeys(map)"> {{recipient}} </li> </ul>
PRACY DEMO
źródło
map
dostępny oryginalny obiekt, możesz go użyć, aby wykorzystać wszystkie zalety mapywhy he needed this kind of requirement
, on może ci lepiej wytłumaczyć :)Jeśli używasz Angular 6.1 lub nowszej, najwygodniej jest użyć 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']]); }
źródło
map
*ngFor
Edytować
W przypadku kątowej wersji 6.1 i nowszych użyj KeyValuePipe zgodnie z sugestią Londeren.
Dla kątowych 6.0 i starszych
Dla ułatwienia możesz stworzyć rurę.
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">
Ponieważ jest czysty, nie będzie wyzwalany przy każdym wykryciu zmiany, ale tylko wtedy, gdy
map
zmieni się odniesienie do zmiennejDemo Stackblitz
źródło
Dzieje się tak, ponieważ
map.keys()
zwraca iterator.*ngFor
może współpracować z iteratorami, alemap.keys()
będą wywoływane przy każdym cyklu wykrywania zmian, tworząc w ten sposób nowe odniesienie do tablicy, powodując wyświetlany błąd. Nawiasem mówiąc, nie zawsze jest to błąd, jak byś o tym tradycyjnie myślał; może nawet nie zepsuć żadnej z twoich funkcji, ale sugeruje, że masz model danych, który wydaje się zachowywać się w szalony sposób - zmienia się szybciej niż detektor zmian sprawdza jego wartość.Jeśli nie chcesz konwertować mapy na tablicę w swoim komponencie, możesz użyć potoku sugerowanego w komentarzach. Jak się wydaje, nie ma innego obejścia.
PS Ten błąd nie pojawi się w trybie produkcyjnym, ponieważ jest bardziej ostrym ostrzeżeniem niż rzeczywistym błędem, ale pozostawienie go nie jest dobrym pomysłem.
źródło
Jak ludzie wspomnieli w komentarzach, potok keyvalue nie zachowuje kolejności wstawiania (co jest głównym celem Map).
W każdym razie, wygląda na to, że jeśli masz obiekt Map i chcesz zachować kolejność, najczystszym sposobem na to jest funkcja entry ():
<ul> <li *ngFor="let item of map.entries()"> <span>key: {{item[0]}}</span> <span>value: {{item[1]}}</span> </li> </ul>
źródło
Poniższy kod przydatny do wyświetlenia w zamówieniu reklamowym mapy .
<ul> <li *ngFor="let recipient of map | keyvalue: asIsOrder"> {{recipient.key}} --> {{recipient.value}} </li> </ul>
Plik .ts dodaj poniższy kod.
asIsOrder(a, b) { return 1; }
źródło