Dizi olarak anahtarı ve eşleme yinelemesi olarak değerleri içeren ngFor döngü eşlemesini kullanarak yineleme


104

Açısal 5'te yeniyim ve yazıdaki başka bir haritayı içeren haritayı yinelemeye çalışıyorum. Bu tür bir haritanın altında açısal olarak nasıl yineleneceği, bileşen için koddur:

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

  }



}

ve şablonu html:

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


</ul>

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

çalışma hatası



çözüm nedir haritamı diziye dönüştürmek istemiyorum
Feroz Siddiqui


teşekkürler çok iyi çalışıyor
Feroz Siddiqui

Yanıtlar:


234

Angular 6.1+ için varsayılan boruyu kullanabilirsiniz keyvalue( Ayrıca gözden geçirin ve oy verin ):

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

ÇALIŞMA DEMOSU


Önceki sürüm için:

Bunun basit bir çözümü, haritayı diziye dönüştürmektir: Array.from

Bileşen Tarafı:

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

Şablon Tarafı:

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

ÇALIŞMA DEMOSU


1
eğer map = new Map <String, Map <String, String >> (); nasıl çalışır?
Feroz Siddiqui

@FerozSiddiqui, cevabı güncelledim ve bunun iç içe geçmiş herhangi bir seviye için işe yarayacağını düşünüyorum.
Vivek Doshi

Sonunda Array'e çevirirsek tüm Harita özelliğini kaybettik. O halde haritanın faydası nedir?
diEcho

1
@ pro.mean, sadece yinelemeyi yinelemek için açısal şablonla döngü yapmak istediğimiz için dönüştürüyoruz. ve hala orijinal nesneye mapsahipseniz, onu Haritanın tüm avantajlarından yararlanmak için kullanabilirsiniz
Vivek Doshi

1
@ pro.mean, bunu şablon tarafında göstermek için dönüştürdük, ancak yine de bileşen tarafında kullanabileceğiniz Map obaject'e sahipsiniz. OP isteyebilirsin why he needed this kind of requirement, sana daha iyi açıklayabilir :)
Vivek Doshi

47

Angular 6.1 veya sonraki bir sürümünü kullanıyorsanız, en uygun yol KeyValuePipe'ı kullanmaktır.

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

3
Umarım insanlar bu cevabı kaydırır ve görürler, çünkü benim maptipim için kullanıma hazır bu kutudan çıkarılan boruyu görene kadar bir refactor yapmak *ngFor
üzereydim

2
Görünüşe göre, anahtar değer haritanın ilk sıralamasını tutmuyor :-(, bunu düzeltmek için karşılaştırma işlevi eklemeniz gerekiyor
Konstantin Vahrushev

1
Bu doğru. Ve işte bir sorun github.com/angular/angular/issues/31420
Londeren

24

Düzenle

Açısal 6.1 ve daha yeni sürümler için, Londeren tarafından önerilen KeyValuePipe'ı kullanın .

Açısal 6.0 ve üstü için

İşleri kolaylaştırmak için bir boru oluşturabilirsiniz.

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

Saf olduğu için, her değişiklik algılamasında tetiklenmeyecek, yalnızca mapdeğişkene referans değiştiğinde tetiklenecektir.

Stackblitz demosu


Borunuzun değişiklikler için kontrol edileceğini ve "saf" olmadığı için her değişiklik algılama döngüsünde tam yinelemesini yapacağını düşünüyorum. Olumsuz oy vermedim ama belki de nedeni bu?
Drenai

5
@Ryan Borular varsayılan olarak saftır. Boruya bir console.log eklerseniz, birden çok kez çağrı almadığını görürsünüz. Ancak kabul edilen çözümdeki bileşen yöntemi bunu yapar ...
David

1
Geriye döndüm!
Uyarılar

10

Bunun nedeni map.keys(), bir yineleyici döndürmesidir. *ngForyineleyicilerle çalışabilir, ancak map.keys()her değişiklik algılama döngüsünde çağrılır, böylece diziye yeni bir referans oluşturur ve gördüğünüz hatayla sonuçlanır. Bu arada, bu her zaman geleneksel olarak düşündüğünüz gibi bir hata değildir ; Hatta herhangi bir işlevselliğinizi bozmayabilir, ancak çılgınca davranan bir veri modeline sahip olduğunuzu gösterir - değişim dedektörünün değerini kontrol ettiğinden daha hızlı değişir.

Haritayı bileşeninizdeki bir diziye dönüştürmek istemiyorsanız, yorumlarda önerilen boruyu kullanabilirsiniz. Göründüğü gibi başka bir çözüm yok.

PS Bu hata, gerçek bir hatadan ziyade çok katı bir uyarı gibi olduğu için üretim modunda gösterilmeyecektir, ancak yine de, bunu öyle bırakmak iyi bir fikir değildir.


1

İnsanların yorumlarda da belirttiği gibi, anahtar değer borusu ekleme sırasını korumaz (bu, Haritanın birincil amacıdır).

Her neyse, bir Harita nesneniz varsa ve sırayı korumak istiyorsanız, bunu yapmanın en temiz yolu, entryler () işlevi:

<ul>
    <li *ngFor="let item of map.entries()">
        <span>key: {{item[0]}}</span>
        <span>value: {{item[1]}}</span>
    </li>
</ul>

Bakınız github.com/angular/angular/issues/31420#issuecomment-635377113 Eğer .entries () kullanmaktan kaçınmalısınız neden
Florian

1

Aşağıdaki kod, harita ekleme siparişinde görüntülenmesi için yararlıdır .

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

.ts dosyası aşağıdaki kodu ekleyin.

asIsOrder(a, b) {
    return 1;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.