我是角度5的新手,并试图在打字稿中迭代包含另一张地图的地图。 如何在角度下迭代这种地图 下面是组件的代码:
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);
}
}
及其模板html为:
<ul>
<li *ngFor="let recipient of map.keys()">
{{recipient}}
</li>
</ul>
<div>{{map.size}}</div>
答案 0 :(得分:72)
对于Angular 6.1 + ,您可以使用默认管道 keyvalue
(Do review also):
<ul>
<li *ngFor="let recipient of map | keyvalue">
{{recipient.key}} --> {{recipient.value}}
</li>
</ul>
<强> WORKING DEMO 强>
对于之前的版本:
一个简单的解决方案是将地图转换为数组: Array.from
组件方:
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());
}
模板面:
<ul>
<li *ngFor="let recipient of getKeys(map)">
{{recipient}}
</li>
</ul>
<强> WORKING DEMO 强>
答案 1 :(得分:23)
如果您使用的是Angular 6.1或更高版本,最方便的方法是使用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']]);
}
答案 2 :(得分:18)
修改强>
对于角度6.1及更高版本,请使用Londeren建议的KeyValuePipe。
适用于角度6.0及以上
为了简化操作,您可以创建管道。
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">
因为它纯粹,它不会在每次更改检测时触发,但仅在map
变量的引用发生变化时
答案 3 :(得分:6)
这是因为map.keys()
返回迭代器。 *ngFor
可以使用迭代器,但map.keys()
将在每个更改检测周期调用,从而产生对数组的新引用,从而导致您看到的错误。顺便说一句,这并不总是像你传统上想到的那样错误;它甚至可能不会破坏你的任何功能,但暗示你有一个似乎以疯狂的方式运行的数据模型 - 变化比变化检测器检查它的值更快。
如果您不想将地图转换为组件中的数组,则可以使用注释中建议的管道。似乎没有其他解决方法。
P.S。这个错误不会在生产模式中显示,因为它更像是一个非常严格的警告,而不是一个实际的错误,但是,这仍然不是一个好主意。
答案 4 :(得分:1)
正如人们在评论中提到的那样,键值管道不保留插入顺序(这是Map的主要目的)。
无论如何,如果您有一个Map对象并想保留订单,那么最干净的方法就是entrys()函数:
<ul>
<li *ngFor="let item of map.entries()">
<span>key: {{item[0]}}</span>
<span>value: {{item[1]}}</span>
</li>
</ul>
答案 5 :(得分:1)
以下代码有助于按地图插入顺序显示。
<ul>
<li *ngFor="let recipient of map | keyvalue: asIsOrder">
{{recipient.key}} --> {{recipient.value}}
</li>
</ul>
.ts文件,添加以下代码。
asIsOrder(a, b) {
return 1;
}
答案 6 :(得分:1)
Angular 的 keyvalue
管道可以使用,但不幸的是它是按键排序的。地图已经有订单,如果能保留订单就好了!
我们可以定义自己的管道 mapkeyvalue
来保留地图中项目的顺序:
import { Pipe, PipeTransform } from '@angular/core';
// Holds a weak reference to its key (here a map), so if it is no longer referenced its value can be garbage collected.
const cache = new WeakMap<ReadonlyMap<any, any>, Array<{ key: any; value: any }>>();
@Pipe({ name: 'mapkeyvalue', pure: true })
export class MapKeyValuePipe implements PipeTransform {
transform<K, V>(input: ReadonlyMap<K, V>): Iterable<{ key: K; value: V }> {
const existing = cache.get(input);
if (existing !== undefined) {
return existing;
}
const iterable = Array.from(input, ([key, value]) => ({ key, value }));
cache.set(input, iterable);
return iterable;
}
}
可以这样使用:
<mat-select>
<mat-option *ngFor="let choice of choicesMap | mapkeyvalue" [value]="choice.key">
{{ choice.value }}
</mat-option>
</mat-select>