webentwicklung-frage-antwort-db.com.de

zugriffsschlüssel und Wert des Objekts mit * ngFor

Etwas verwirrt darüber, wie ein Key and Value eines Objekts in angle2 abgerufen wird, während * ngFor für die Iteration des Objekts verwendet wird. Ich weiß in Winkel 1.x gibt es Syntax wie 

ng-repeat="(key, value) in demo"

aber in Angle2 weiß ich nicht, dass ich dasselbe versucht habe, aber nicht erfolgreich war. Ich habe den folgenden Code ausprobiert, aber nicht ausgeführt, bitte sagen Sie mir, wo ich falsch arbeite.

<ul>
  <li *ngFor='#key of demo'>{{key}}</li>
</ul>

demo = {
    'key1': [{'key11':'value11'}, {'key12':'value12'}],
    'key2': [{'key21':'value21'}, {'key22':'value22'}],
  }

hier ist plnkr, wo ich das gleiche ausprobiert habe: http://plnkr.co/edit/mIj619FncOpfdwrR0KeG?p=preview

Ich möchte key1 und key2 mit * ngFor dynamisch abrufen. Wie bekomme ich das? Ich habe viel nach der Idee gesucht, Pipe zu benutzen, aber wie ich es benutze, weiß ich nicht ... Gibt es eine Inbuild-Pipe, um dasselbe in Angle2 zu tun?

249
Pardeep Jain

Wie in latest Version von Angular (v6.1.0) hat Angular Team eine neue eingebaute Pipe für die gleichnamige keyvalue-Pipe hinzugefügt, mit der Sie Objekte, Karten und Arrays im common-Modul des Winkelpakets durchlaufen können .Zum Beispiel -

<div *ngFor="let item of testObject | keyvalue">
    Key: <b>{{item.key}}</b> and Value: <b>{{item.value}}</b>
</div>

Arbeitsbeispiel

hier finden Sie weitere nützliche Informationen.

Wenn Sie Angular v5 oder darunter verwenden oder die Verwendung von Pipe erreichen möchten, folgen Sie dieser Antwort

104
Pardeep Jain

Habe Object.keys in der Vorlage verfügbar und verwende es in *ngFor.

@Component({
  selector: 'app-myview',
  template: `<div *ngFor="let key of objectKeys(items)">{{key + ' : ' + items[key]}}</div>`
})

export class MyComponent {
  objectKeys = Object.keys;
  items = { keyOne: 'value 1', keyTwo: 'value 2', keyThree: 'value 3' };
  constructor(){}
}
272
tomtastico

Sie können eine benutzerdefinierte Pipe erstellen, um die Liste der Schlüssel für jedes Element zurückzugeben. __ So ähnlich:

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

@Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
  transform(value, args:string[]) : any {
    let keys = [];
    for (let key in value) {
      keys.Push(key);
    }
    return keys;
  }
}

und benutze es so:

<tr *ngFor="let c of content">           
  <td *ngFor="let key of c | keys">{{key}}: {{c[key]}}</td>
</tr>

Bearbeiten

Sie können auch einen Eintrag mit Schlüssel und Wert zurückgeben:

@Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
  transform(value, args:string[]) : any {
    let keys = [];
    for (let key in value) {
      keys.Push({key: key, value: value[key]});
    }
    return keys;
  }
}

und benutze es so:

<span *ngFor="let entry of content | keys">           
  Key: {{entry.key}}, value: {{entry.value}}
</span>
195

Aktualisieren

In 6.1.0-beta.1KeyValuePipewurde _ eingeführt https://github.com/angular/angular/pull/24319

<div *ngFor="let item of {'b': 1, 'a': 1} | keyvalue">
  {{ item.key }} - {{ item.value }}
</div>

Plunker Beispiel

Vorherige Version

Ein anderer Ansatz ist die Erstellung einer NgForIn Direktive, die wie folgt verwendet wird:

<div *ngFor="let key in obj">
   <b>{{ key }}</b>: {{ obj[key] }}
</div>

Plunker Beispiel

ngforin.directive.ts

@Directive({
  selector: '[ngFor][ngForIn]'
})
export class NgForIn<T> extends NgForOf<T> implements OnChanges {

  @Input() ngForIn: any;

  ngOnChanges(changes: NgForInChanges): void {
    if (changes.ngForIn) {
      this.ngForOf = Object.keys(this.ngForIn) as Array<any>;

      const change = changes.ngForIn;
      const currentValue = Object.keys(change.currentValue);
      const previousValue = change.previousValue ? Object.keys(change.previousValue) : undefined;
      changes.ngForOf =  new SimpleChange(previousValue, currentValue, change.firstChange);

      super.ngOnChanges(changes);
    }
  }
}
32
yurzui

Ausarbeitung der Antwort von @ Thierry mit Beispiel.

Es gibt keine eingebaute Pipe oder Methode, um key and value aus der * ngFor-Schleife zu erhalten. Wir müssen also eine eigene Pipe erstellen. Wie Thierry sagte, hier ist die Antwort mit Code.

** Die Pipe-Klasse implementiert die Transformationsmethode der PipeTransform-Schnittstelle, die einen Eingabewert und ein optionales Array von Parameterzeichenfolgen verwendet und den transformierten Wert zurückgibt.

** Die Transformationsmethode ist für eine Pipe unerlässlich. Die PipeTransform-Schnittstelle definiert diese Methode und leitet sowohl das Tooling als auch den Compiler. Es ist optional; Angular sucht und führt die Transformationsmethode unabhängig davon aus . Weitere Informationen zu Pipe siehe hier

import {Component, Pipe, PipeTransform} from 'angular2/core';
import {CORE_DIRECTIVES, NgClass, FORM_DIRECTIVES, Control, ControlGroup, FormBuilder, Validators} from 'angular2/common';

@Component({
    selector: 'my-app',
    templateUrl: 'mytemplate.html',
    directives: [CORE_DIRECTIVES, FORM_DIRECTIVES],
    pipes: [KeysPipe]
})
export class AppComponent { 

  demo = {
    'key1': 'ANGULAR 2',
    'key2': 'Pardeep',
    'key3': 'Jain',
  }
}


@Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
  transform(value, args:string[]) : any {
    let keys = [];
    for (let key in value) {
      keys.Push({key: key, value: value[key]});
    }
    return keys;
  }
}

und HTML-Teil ist: 

<ul>
  <li *ngFor='#key of demo | keys'>
   Key: {{key.key}}, value: {{key.value}}
  </li>
</ul>

Working Plnkr http://plnkr.co/edit/50LlK0k6OnMnkc2kNHM2?p=preview

update auf RC

wie von user6123723 (danke) in kommentar hier vorgeschlagen, ist update.

<ul>
  <li *ngFor='let key of demo | keys'>
   Key: {{key.key}}, value: {{key.value}}
  </li>
</ul>
23
Pardeep Jain

@Marton hatte einen wichtigen Einwand gegen die akzeptierte Antwort mit der Begründung, dass die Pipe bei jeder Änderungserkennung eine neue Sammlung erstellt. Ich würde stattdessen einen HtmlService erstellen, der eine Reihe von Hilfsfunktionen bereitstellt, die die Ansicht wie folgt verwenden kann:

@Component({
  selector: 'app-myview',
  template: `<div *ngFor="let i of html.keys(items)">{{i + ' : ' + items[i]}}</div>`
})
export class MyComponent {
  items = {keyOne: 'value 1', keyTwo: 'value 2', keyThree: 'value 3'};
  constructor(private html: HtmlService){}
}

@Injectable()
export class HtmlService {
  keys(object: {}) {
    return Object.keys(object);
  }
  // ... other useful methods not available inside html, like isObject(), isArray(), findInArray(), and others...
}
18
Stephen Paul

Ab Angular 6.1 können Sie den Schlüsselwert pipe verwenden:

<div *ngFor="let item of testObject | keyvalue">
    Key: <b>{{item.key}}</b> and Value: <b>{{item.value}}</b>
</div>

Es hat jedoch den Nachteil, dass die Ergebnisliste nach dem Schlüsselwert sortiert wird. Wenn Sie etwas Neutrales benötigen:

@Pipe({ name: 'keyValueUnsorted', pure: false  })
export class KeyValuePipe implements PipeTransform {
  transform(input: any): any {
    let keys = [];
    for (let key in input) {
      if (input.hasOwnProperty(key)) {
        keys.Push({ key: key, value: input[key]});
      }
    }
    return keys;
  }
}

Vergessen Sie nicht, das Attribut pure: false pipe anzugeben. In diesem Fall wird die Pipe bei jedem Änderungserkennungszyklus aufgerufen, auch wenn sich die Eingabereferenz nicht geändert hat (wenn Sie einem Objekt Eigenschaften hinzufügen). 

16
Gerard Carbó

Wenn Sie Lodash bereits verwenden, können Sie diesen einfachen Ansatz verwenden, der sowohl Schlüssel als auch Wert beinhaltet:

<ul>
  <li *ngFor='let key of _.keys(demo)'>{{key}}: {{demo[key]}}</li>
</ul>

Fügen Sie in der TypeScript-Datei Folgendes hinzu:

import * as _ from 'lodash';

und in der exportierten Komponente Folgendes enthalten:

_: any = _;
15
Jeremy Moritz

Vielen Dank für das Rohr, aber ich musste einige Änderungen vornehmen, bevor ich es in eckig 2 RC5 verwenden konnte. Die Pipe-Importlinie wurde geändert und der Initialisierung des Key-Arrays wurde der Typ any hinzugefügt.

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

 @Pipe({name: 'keys'})
 export class KeysPipe implements PipeTransform {
 transform(value) {
   let keys:any = [];
   for (let key in value) {
      keys.Push( {key: key, value: value[key]} );
    }
     return keys;
  }
}
8
Adam Winnipass

Es gibt eine echte Nice-Bibliothek, die dies unter anderen Nice-Pfeifen tut. Es heißt ngx-pipe

Zum Beispiel gibt key pipe Schlüssel für ein Objekt zurück, und values ​​pipe gibt Werte für ein Objekt zurück:

keys pipe

<div *ngFor="let key of {foo: 1, bar: 2} | keys">{{key}}</div> 
<!-- Output: 'foo' and 'bar -->

Wertepipe

<div *ngFor="let value of {foo: 1, bar: 2} | values">{{value}}</div>
<!-- Output: 1 and 2 -->

Sie müssen keine eigene Pipe erstellen :)

6
RichieRock

Keine der Antworten hier hat für mich aus dem Kasten heraus funktioniert.

Erstellen Sie pipes/keys.ts mit Inhalt:

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

@Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform
{
    transform(value:any, args:string[]): any {
        let keys:any[] = [];
        for (let key in value) {
            keys.Push({key: key, value: value[key]});
        }
        return keys;
    }
}

Zu app.module.ts hinzufügen (Ihr Hauptmodul):

import { KeysPipe } from './pipes/keys';

und fügen Sie dann zu Ihrem Modul Deklarationsarray etwas hinzu:

@NgModule({
    declarations: [
        KeysPipe
    ]
})
export class AppModule {}

Dann können Sie in Ihrer Ansichtsvorlage Folgendes verwenden:

<option *ngFor="let entry of (myData | keys)" value="{{ entry.key }}">{{ entry.value }}</option>

Hier ist eine gute Referenz, die ich gefunden habe, wenn Sie mehr lesen möchten.

6
cjohansson

Hier ist die einfache Lösung

Sie können dafür TypeScript-Iteratoren verwenden

import {Component} from 'angular2/core';
declare var Symbol;
@Component({
    selector: 'my-app',
    template:`<div>
    <h4>Iterating an Object using TypeScript Symbol</h4><br>
Object is : <p>{{obj | json}}</p>
</div>
============================<br>
Iterated object params are:
<div *ngFor="#o of obj">
{{o}}
</div>

`
})
export class AppComponent {
  public obj: any = {
    "type1": ["A1", "A2", "A3","A4"],
    "type2": ["B1"],
    "type3": ["C1"],
    "type4": ["D1","D2"]
  };

  constructor() {
    this.obj[Symbol.iterator] =  () => {
          let i =0;

          return {
            next: () => {
              i++;
              return {
                  done: i > 4?true:false,
                  value: this.obj['type'+i]
              }
            }
          }
    };
  }
}

http://plnkr.co/edit/GpmX8g?p=info

3
sudheer KB

Ändern Sie den Demo-Typ in Array oder iterieren Sie über Ihr Objekt und drücken Sie auf ein anderes Array

public details =[];   
Object.keys(demo).forEach(key => {
      this.details.Push({"key":key,"value":demo[key]);
    });

und von html: 

<div *ngFor="obj of details">
  <p>{{obj.key}}</p>
  <p>{{obj.value}}</p>
  <p></p>
</div>
1

Index verwenden:

<div *ngFor="let value of Objects; index as key">

Verwendungszweck:

{{key}} -> {{value}}
1
Adonias Vasquez

Ich denke, Object.keys ist die beste Lösung für dieses Problem. Für jeden, der auf diese Antwort stößt und herauszufinden versucht, warum Object.keys ihnen ['0', '1'] anstelle von ['key1', 'key2'] gibt, ist dies eine warnende Geschichte - hüten Sie den Unterschied zwischen " von "und" in ":

Ich habe bereits Object.keys verwendet, etwas ähnliches: 

interface demo {
    key: string;
    value: string;
}

createDemo(mydemo: any): Array<demo> {
    const tempdemo: Array<demo> = [];

    // Caution: use "of" and not "in"
    for (const key of Object.keys(mydemo)) {
        tempdemo.Push(
            { key: key, value: mydemo[key]}
        );
    }

    return tempdemo;
}

Statt jedoch 

for (const key OF Object.keys(mydemo)) {

Ich hatte versehentlich geschrieben

for (const key IN Object.keys(mydemo)) {

die "funktionierte" einwandfrei ohne fehler und kehrte zurück 

[{key: '0', value: undefined}, {key: '1', value: undefined}]

Das kostete mich etwa 2 Stunden googeln und fluchen.

(Ohrfeigen)

1
Ciaran Bruen

wenn Sie dies versuchen, erhalten Sie den Schlüssel des dynamischen Objekts von dynamic

myObj['key']
0
Rizo

Sie müssen es erst einmal so machen, ich weiß es nicht sehr effizient, da Sie das Objekt, das Sie von Firebase erhalten, nicht konvertieren wollen.

    this.af.database.list('/data/' + this.base64Email).subscribe(years => {
        years.forEach(year => {

            var localYears = [];

            Object.keys(year).forEach(month => {
                localYears.Push(year[month])
            });

            year.months = localYears;

        })

        this.years = years;

    });
0
kevinius