Frage Iterieren über Objekt in Angular


Ich versuche, einige Dinge in Angular 2 Alpha 28 zu tun, und habe ein Problem mit Wörterbüchern und NgFor.

Ich habe eine Schnittstelle in TypeScript, die so aussieht:

interface Dictionary {
    [ index: string ]: string
}

In JavaScript wird dies in ein Objekt übersetzt, das mit Daten wie folgt aussehen könnte:

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

Ich möchte darüber iterieren und habe das versucht:

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

Aber ohne Erfolg, keine der folgenden funktionierte:

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

In allen Fällen erhalte ich Fehler wie "Unerwarteter Token" oder "Kann 'iterableDiff' Pipe Support Object nicht finden"

Was fehlt mir hier? Ist das nicht mehr möglich? (Die erste Syntax funktioniert in Angular 1.x) oder ist die Syntax für das Iterieren über ein Objekt anders?


75
2017-07-18 11:30


Ursprung


Antworten:


Es scheint, dass sie die Syntax von ng1 nicht unterstützen wollen.

Laut Miško Hevery (Referenz):

Karten haben keine Befehle in Schlüsseln und daher ist die Iteration nicht vorhersehbar.   Dies wurde in ng1 unterstützt, aber wir denken, dass es ein Fehler war und nicht   in NG2 unterstützt werden

Der Plan ist eine mapToIterable-Pipe zu haben

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

Um also über Ihr Objekt zu iterieren, müssen Sie eine "Pipe" verwenden. Derzeit gibt es keine Rohr implementiert das tut das.

Um dies zu umgehen, hier ein kleines Beispiel, das über die Schlüssel iteriert:

Komponente:

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



versuche diese Pfeife zu benutzen

@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



2018 Aktualisierung:

Wie die anderen Antworten schon erwähnt haben, wird es in ngx nicht unterstützt. Hier ist ein Workaround mit Schlüssel-Wert-Paare:

Das Rohr:

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

Die Verwendung:

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

Stackblitz Beispiel: https://stackblitz.com/edit/map-to-iterable-pipe


31
2018-02-08 01:14



Neben der Antwort von @ obscur finden Sie hier ein Beispiel, wie Sie auf beide zugreifen können key und value aus dem @View.

Rohr:

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

}

Aussicht:

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

Wenn das Objekt also so aussehen würde:

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

Das Ergebnis wäre:

Vorname: Daario
Nachname: Naharis

Vorname: Victarion
Nachname: Greyjoy

Vorname: Quentyn
Nachname: Ball


18
2018-03-03 18:14



Hinzufügen zu SimonHawomes ausgezeichnete Antwort. Ich habe eine prägnante Version erstellt, die einige der neuen Typoskript-Funktionen nutzt. Mir ist klar, dass SimonHaweses Version absichtlich ausführlich ist, um die zugrunde liegenden Details zu erklären. Ich habe auch eine frühzeitige Überprüfung hinzugefügt, damit die Pipe funktioniert falsch Werte. Z. B. wenn die Karte ist null.

Beachten Sie, dass die Verwendung einer Iterator-Transformation (wie hier ausgeführt) effizienter sein kann, da wir keinen Speicher für ein temporäres Array reservieren müssen (wie in einigen anderen Antworten).

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



Hier ist eine Variation einiger der obigen Antworten, die mehrere Transformationen (keyval, key, value) unterstützen:

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

Verwendung

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



Ich hatte ein ähnliches Problem, baute etwas für Objekte und Maps.

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



Angular 2.x && Angular 4.x unterstützt dies nicht out of the box

Sie können diese beiden Pipes verwenden, um entweder zu iterieren Schlüssel oder von Wert.

Schlüsselpfeife:

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

Werte pipe:

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])
  }
}

Wie benutzt man:

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