web-dev-qa-db-ja.com

キーを文字列として、値をマップ反復として含むngForループマップを使用して反復する方法

私はangular 5が初めてで、TypeScriptで別のマップを含むマップを反復しようとしています。コンポーネントのコードは、以下のangularのこの種類のマップの下で反復する方法です。

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>

runtime error

51
Feroz Siddiqui

Angular 6.1 +の場合、デフォルトのパイプkeyvalue を使用できます=レビューも行う ):

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

WORKING DEMO


以前のバージョンの場合:

これに対する単純な解決策の1つは、マップを配列に変換することです: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

87
Vivek Doshi

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

編集

angular 6.1以降の場合、Londerenが提案する KeyValuePipe を使用します。

angular 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変数への参照が変更された場合にのみトリガーされます

Stackblitzデモ

19
David

これは、map.keys()がイテレータを返すためです。 *ngForはイテレータで動作しますが、map.keys()は変更検出サイクルごとに呼び出されるため、配列への新しい参照が生成され、表示されるエラーが発生します。ところで、これはあなたが伝統的に考えているように、常にerrorであるとは限りません。機能を壊すことはないかもしれませんが、異常な方法で動作しているように見えるデータモデルがあることを示唆しています。変更検出器が値をチェックするよりも速く変化します。

コンポーネント内でマップを配列に変換したくない場合は、コメントで提案されているパイプを使用できます。考えられるように、他の回避策はありません。

追伸このエラーは、実際のエラーではなく、非常に厳密な警告に近いため、本番モードでは表示されませんが、そのままにしておくことはお勧めできません。

6
Armen Vardanyan