Soru Açısal olarak nesne üzerinde yineleyin


Angular 2 Alpha 28'de bazı şeyler yapmaya çalışıyorum ve sözlükler ve NgFor ile ilgili bir sorun yaşıyorum.

TypeScript'te şöyle bir arayüz var:

interface Dictionary {
    [ index: string ]: string
}

JavaScript'te, bu, verilerin aşağıdaki gibi görünebileceği bir nesneye dönüştürülür:

myDict={'key1':'value1','key2':'value2'}

Bunu tekrarlamak istiyorum ve bunu denedim:

<div *ngFor="(#key, #value) of myDict">{{key}}:{{value}}</div>

Ancak, boşuna, aşağıdakilerden hiçbiri ya işe yaramadı:

<div *ngFor="#value of myDict">{{value}}</div>
<div *ngFor="#value of myDict #key=index">{{key}}:{{value}}</div>

Her durumda "Beklenmeyen belirteç" veya "iterableDiff 'boru destekleme nesnesini bulamıyor" gibi hatalar alıyorum

Burada neyi özlüyorum? Bu artık mümkün değil mi? (İlk sözdizimi, Angular 1.x'te çalışır) veya bir nesne üzerinde yinelemek için farklı bir sözdizimi mi?


76
2017-07-18 11:30


Menşei


"Sözlük" nedir? Bu terimi bir JavaScript, Angular veya TypeScript bağlamında hiç görmedim veya duymadım. Y


Cevaplar:


Görünüşe göre ng1'den gelen sözdizimini desteklemek istemiyorlar.

Miško Hevery'ye göre (referans):

Haritalar, anahtarlarda hiçbir emir içermez ve dolayısıyla yineleme önceden tahmin edilemez.   Bu ng1'de desteklendi, ancak bunun bir hata olduğunu düşünüyoruz ve olmayacak   NG2'de desteklenmeli

Plan bir mapToIterable boru sahip olmaktır

<div *ngFor"var item of map | mapToIterable">

Yani nesnenin üzerinde yinelemek için bir "boru" kullanmanız gerekecek. Şu anda yok boru Bunu uyguladı.

Bir geçici çözüm olarak, burada anahtarların üzerinde yinelenen küçük bir örnek:

Bileşen:

import {Component} from 'angular2/core';

@Component({
  selector: 'component',
  templateUrl: `
       <ul>
       <li *ngFor="#key of keys();">{{key}}:{{myDict[key]}}</li>
       </ul>
  `
})
export class Home {
  myDict : Dictionary;
  constructor() {
    this.myDict = {'key1':'value1','key2':'value2'};
  }

  keys() : Array<string> {
    return Object.keys(this.myDict);
  }
}

interface Dictionary {
    [ index: string ]: string
}

68
2017-07-21 11:22



nesneyle aynı şeyi deniyorum key gibi number ve value gibi string ama açısal hata atıyor expression has changed after it was checked ? neden böyle bir fikrin var? - Pardeep Jain
Evet bu benim için de oluyor. Ve aynı zamanda @ obsur'un çözümünü kullanırsam. - user2294382


bu boruyu kullanmayı dene

@Pipe({ name: 'values',  pure: false })
export class ValuesPipe implements PipeTransform {
  transform(value: any, args: any[] = null): any {
    return Object.keys(value).map(key => value[key]);
  }
}

<div *ngFor="#value of object | values"> </div>

60
2017-12-03 19:26



Brilliant, ve ben referansı anahtarda tutmak istiyorsam, sadece bir nesneyi hem anahtar hem de değerle eşleyeceğim. Bir çok cevabı kabul edilmiş cevap olarak işaretleyebilmeyi isterdim, çünkü bu benim sorunumun çözümüydi, işaretlenmiş cevap ise benim soruğumun cevabıydı. - Rickard Staaf
@obscur - Eğer şimdi yukarıda yaparsam, angular2.beta.0.0 kullanarak "ifadesi kontrol edildikten sonra değiştirildi" hatası alıyorum. Düşüncesi olan var mı? - user2294382
Thats çünkü saf: yanlış bir enjeksiyonu gerektirirStrapi enjekte gerektirir - Judson Terrell
Neden onu saf dışı bırakacak? - tom10271


2018 Güncellemesi:

Diğer cevapların da belirttiği gibi, ngx'de desteklenmiyor, işte burada bir çözüm var. anahtar değeri çiftleri:

Boru:

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
  name: 'mapToIterable'
})
export class MapToIterable implements PipeTransform {
  transform(dict: Object) {
    var a = [];
    for (var key in dict) {
      if (dict.hasOwnProperty(key)) {
        a.push({key: key, val: dict[key]});
      }
    }
    return a;
  }
}

Kullanım:

<div *ngFor="let keyValuePair of someObject | mapToIterable">
  This is the key {{keyValuePair.key}} and this is the value {{keyValuePair.val}}.
</div>

Stackblitz Örneği: https://stackblitz.com/edit/map-to-iterable-pipe


33
2018-02-08 01:14



Eklemelisin implements PipeTransform sınıf tanımında angular.io/guide/pipes#custom-pipes) - toioski
@toioski teşekkürler, ekledim ve for döngüsünün yeni sözdizimine güncellendi. - bersling
Harika cevap, bunu Sözlük'üm için kullan. Değerlerim [{}] sona erdi ve {} değil, ancak keyValuePair.val [0] yapmalıydım - jhhoff02
Teşekkürler. Harika çalışıyor - Johansrk


@ Obscur'un cevabına ek olarak, burada her ikisine de nasıl erişebileceğinize dair bir örnektir. key ve value @View'den.

Boru:

@Pipe({
   name: 'keyValueFilter'
})

export class keyValueFilterPipe {
    transform(value: any, args: any[] = null): any {

        return Object.keys(value).map(function(key) {
            let pair = {};
            let k = 'key';
            let v = 'value'


            pair[k] = key;
            pair[v] = value[key];

            return pair;
        });
    }

}

Görünüm:

<li *ngFor="#u of myObject | 
keyValueFilter">First Name: {{u.key}} <br> Last Name: {{u.value}}</li>

Yani eğer nesne şöyle görünecekti:

myObject = {
    Daario: Naharis,
    Victarion: Greyjoy,
    Quentyn: Ball
}

Oluşturulan sonuç şöyle olurdu:

İlk isim: Daario
Soyadı: Naharis

İlk isim: Victarion
Soyadı: Greyjoy

İlk isim: Quentyn
Soyadı: Top


18
2018-03-03 18:14



Benim için oldukça kolay çalıştı! Teşekkürler - Vlad
Görünümünüzü değiştirmeniz gerektiğini belirtmeniz gereken tek bir şey: <li *ngFor="let u of myObject | keyValueFilter">First Name: {{u.key}} <br> Last Name: {{u.value}}</li>. +1 benden. - sib10
Harika! Teşekkür ederim. - Maxime Lafarie


SimonHawesome'ın eklenmesi mükemmel cevap. Bazı yeni yazı karakterlerini kullanan kısa bir versiyon yaptım. SimonHawesome'ın versiyonunun, altta yatan detayları açıklamak için kasıtlı olarak önemli olduğunu anlıyorum. Ayrıca borunun işe yaraması için erken bir kontrol ekledim falsy değerler. Örneğin, harita null.

Bir yineleyici dönüşümü (burada yapıldığı gibi) kullanmak, geçici bir dizi için bellek ayırmaya gerek duymadığımızdan daha verimli olabilir (diğer cevaplarda da yapıldığı gibi).

import {Pipe, PipeTransform} from '@angular/core';

@Pipe({
    name: 'mapToIterable'
})
export class MapToIterable implements PipeTransform {
    transform(map: { [key: string]: any }, ...parameters: any[]) {
        if (!map)
            return undefined;
        return Object.keys(map)
            .map((key) => ({ 'key': key, 'value': map[key] }));
    }
}

12
2018-05-27 09:15



Bu konuya bir aşk, bir yorum ontop başka bir bina ile! Kodunu gördüğümde aynı şeyi yazmak üzereydim. - David
Bu çözümdeki tek şey: uygulamalıdır PipeTransform - iRaS
@iRaS İyi nokta. Cevabımı güncelledim. Ayrıca, null yerine undefined. - Frederik Aalund


Yukarıdaki cevaplardan bazılarının birden fazla dönüşümü destekleyen bir varyasyonu (anahtar, anahtar, değer):

import { Pipe, PipeTransform } from '@angular/core';

type Args = 'keyval'|'key'|'value';

@Pipe({
  name: 'mapToIterable',
  pure: false
})
export class MapToIterablePipe implements PipeTransform {
  transform(obj: {}, arg: Args = 'keyval') {
    return arg === 'keyval' ?
        Object.keys(obj).map(key => ({key: key, value: obj[key]})) :
      arg === 'key' ?
        Object.keys(obj) :
      arg === 'value' ?
        Object.keys(obj).map(key => obj[key]) :
      null;
  }
}

kullanım

map = {
    'a': 'aee',
    'b': 'bee',
    'c': 'see'
}

<div *ngFor="let o of map | mapToIterable">{{o.key}}: {{o.value}}</div>
  <div>a: aee</div>
  <div>b: bee</div>
  <div>c: see</div>

<div *ngFor="let o of map | mapToIterable:'keyval'">{{o.key}}: {{o.value}}</div>
  <div>a: aee</div>
  <div>b: bee</div>
  <div>c: see</div>

<div *ngFor="let k of map | mapToIterable:'key'">{{k}}</div>
  <div>a</div>
  <div>b</div>
  <div>c</div>

<div *ngFor="let v of map | mapToIterable:'value'">{{v}}</div>
  <div>aee</div>
  <div>bee</div>
  <div>see</div>

9
2018-01-11 22:32



pure: false anlık yansımalar için gerçekten önemlidir. - Fırat KÜÇÜK


Benzer bir sorun yaşadım, nesneler ve Haritalar için bir şeyler yaptım.

import { Pipe } from 'angular2/core.js';

/**
 * Map to Iteratble Pipe
 * 
 * It accepts Objects and [Maps](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)
 * 
 * Example:
 * 
 *  <div *ngFor="#keyValuePair of someObject | mapToIterable">
 *    key {{keyValuePair.key}} and value {{keyValuePair.value}}
 *  </div>
 * 
 */
@Pipe({ name: 'mapToIterable' })
export class MapToIterable {
  transform(value) {
    let result = [];
    
    if(value.entries) {
      for (var [key, value] of value.entries()) {
        result.push({ key, value });
      }
    } else {
      for(let key in value) {
        result.push({ key, value: value[key] });
      }
    }

    return result;
  }
}


4
2018-04-13 23:27



Bu iyi çalışır, ancak TypeScript'te eklemeniz gerekir implements PipeTransform sınıf tanımına - GeorgDangl


Açısal 2.x && Açısal 4.x kutunun dışında bunu desteklemez

Bunu yapmak için bu iki boruyu kullanabilirsiniz. anahtar veya tarafından değer.

Anahtar boru:

import {Pipe, PipeTransform} from '@angular/core'

@Pipe({
  name: 'keys',
  pure: false
})
export class KeysPipe implements PipeTransform {
  transform(value: any, args: any[] = null): any {
    return Object.keys(value)
  }
}

Değerler boru:

import {Pipe, PipeTransform} from '@angular/core'

@Pipe({
  name: 'values',
  pure: false
})
export class ValuesPipe implements PipeTransform {
  transform(value: any, args: any[] = null): any {
    return Object.keys(value).map(key => value[key])
  }
}

Nasıl kullanılır:

let data = {key1: 'value1', key2: 'value2'}

<div *ngFor="let key of data | keys"></div>
<div *ngFor="let value of data | values"></div>

3
2018-05-30 06:15