clé d'accès et valeur de l'objet en utilisant * ngFor

peu confus sur la façon d'obtenir Key and Value d'objet en angular2 tout en usng * ngFor pour l'itération sur l'objet. je sais angulaire 1.X il y a une syntaxe comme

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

mais à angular2, Je ne sais pas si j'ai été aussi fatiguée, mais je n'ai pas eu de succès. j'ai essayé le code ci-dessous, mais je ne me suis pas enfui.s'il vous plaît, dites-moi où je me trompe.

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

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

voici plnkr où j'ai essayé le même : http://plnkr.co/edit/mIj619FncOpfdwrR0KeG?p=preview

je veux obtenir key1 et key2 en utilisant dynamiquement *ngFor. Comment l'obtenir? j'ai cherché beaucoup trouvé l'idée d'utiliser pipe mais comment l'utiliser Je ne sais pas. y a-t-il un tuyau intégré pour faire la même chose à angular2 ?

205
demandé sur Patricio Vargas 2016-02-21 13:28:24

15 réponses

avoir Object.keys accessible dans le modèle et l'utiliser dans *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(){}
}
214
répondu tomtastico 2017-08-11 15:43:43

vous pouvez créer un tuyau personnalisé pour retourner la liste des clés pour chaque élément. Quelque chose comme ça:

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

et l'utiliser comme ça:

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

Modifier

vous pouvez également retourner une entrée contenant à la fois la clé et la valeur:

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

et l'utiliser comme ça:

<span *ngFor="let entry of content | keys">           
  Key: {{entry.key}}, value: {{entry.value}}
</span>
181
répondu Thierry Templier 2018-01-17 14:35:24

As in latest release of Angular (v6.1.0) , Angular Team a ajouté un nouveau tube intégré pour le même nommé keyvalue pipe pour vous aider à itérer à travers des objets, des cartes, et des tableaux, dans le common module de paquet angulaire. Par exemple -

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

Exemple Travaillé

voir ici pour plus d'informations utiles -

si vous utilisez un angle v5 ou inférieur ou si vous voulez utiliser un tuyau, suivez cette réponse

32
répondu Pardeep Jain 2018-10-03 09:51:40

mise à Jour

Dans 6.1.0-bêta.1 KeyValuePipe a été introduit https://github.com/angular/angular/pull/24319

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

"Exemple De Plongeur

version précédente

une autre approche consiste à créer une directive NgForIn qui sera utilisée comme:

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

"Exemple De Plongeur

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);
    }
  }
}
26
répondu yurzui 2018-09-25 09:30:14

élaboration de la réponse de @Thierry avec exemple.

il n'y a pas de tuyau ou de méthode intégré pour obtenir key and value de la boucle *ngFor. nous devons donc créer des tuyau pour la même chose. comme thierry l'a dit, voici la réponse avec le code.

* * la classe pipe implémente la méthode transform de L'interface PipeTransform qui prend une valeur d'entrée et un tableau optionnel de chaînes de paramètres et renvoie la valeur transformée.

** La méthode transform est essentielle pour un tuyau. L'interface PipeTransform définit cette méthode et guide à la fois l'outillage et le compilateur. Il est optionnel; Angular recherche et exécute la méthode transform indépendamment. pour plus d'informations concernant la pipe se référer ici

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

et la partie HTML est:

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

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

mise à jour de RC

comme suggéré par user6123723(merci) dans le commentaire voici la mise à jour.

<ul>
  <li *ngFor='let key of demo | keys'>
   Key: {{key.key}}, value: {{key.value}}
  </li>
</ul>
21
répondu Pardeep Jain 2016-08-21 08:20:11

@Marton avait une objection importante à la réponse acceptée au motif que la conduite crée une nouvelle collection sur chaque détection de changement. Je créerais plutôt un HtmlService qui fournit une gamme de fonctions utilitaires que la vue peut utiliser comme suit:

@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
répondu Stephen Paul 2018-07-17 06:58:52

si vous utilisez déjà Lodash, vous pouvez faire cette approche simple qui inclut à la fois la clé et la valeur:

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

dans le fichier dactylographié, inclure:

import * as _ from 'lodash';

et dans la composante exportée, inclure:

_: any = _;
14
répondu Jeremy Moritz 2018-07-18 03:21:21

de L'angle 6.1 vous pouvez utiliser le keyvalue pipe:

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

mais il a l'inconvénient qui trie la liste résultante par la valeur clé. Si vous avez besoin de quelque chose de neutre:

@Pipe({ name: 'keyValueUnsorted' })
export class KeyValuePipe implements PipeTransform {
  transform(value: any, args: string[]): any {
    let keys = [];
    for (let key in value) {
      keys.push({ key: key, value: value[key]});
    }
    return keys;
  }
}
8
répondu Gerard Carbó 2018-08-21 07:33:15

Merci pour le tuyau, mais j'ai dû faire quelques changements avant de pouvoir l'utiliser en angle 2 RC5. A changé la ligne D'importation de Pipe et a aussi ajouté le type de any à l'initialisation du tableau de clés.

 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;
  }
}
7
répondu Adam Winnipass 2016-08-27 11:23:44

Aucune des réponses ici a fonctionné pour moi hors de la boîte, voici ce qui a fonctionné pour moi:

créer pipes/keys.ts avec contenu:

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

ajouter à app.module.ts (votre module principal):

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

et ensuite ajouter à votre tableau de déclarations de modules quelque chose comme ceci:

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

alors dans votre modèle de vue vous pouvez utiliser quelque chose comme ceci:

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

Ici est une bonne référence que j'ai trouvé, si vous voulez en savoir plus.

6
répondu cjohansson 2017-05-18 11:52:00

il y a une très belle bibliothèque qui fait ça parmi d'autres belles pipes. Ça s'appelle ngx-pipes .

par exemple, le tube de touches renvoie des touches pour un objet, et le tube de valeurs renvoie des valeurs pour un objet:

clés à pipe

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

valeurs tuyau

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

pas besoin de créer votre propre pipe personnalisée:)

6
répondu RichieRock 2017-05-22 08:54:45

Voici la solution simple

vous pouvez utiliser des itérateurs dactylographiés pour ce

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
répondu sudheer KB 2016-09-16 12:07:48

je pense objet.touches, c'est la meilleure solution à ce problème. Pour ceux qui rencontrent cette réponse et qui essaient de découvrir pourquoi ils S'y opposent.keys leur donne ['0',' 1'] au lieu de ['key1', 'key2'], une mise en garde - méfiez-vous de la différence entre "de" et" dans":

j'utilisais déjà Object.touches, quelque chose de semblable à ceci:

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

cependant, au lieu de

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

j'avais écrit par inadvertance

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

qui "a fonctionné" parfaitement bien sans aucune erreur et retourné

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

qui m'a coûté environ 2 heures à googler et à maudire..

(gifle le front)

1
répondu Ciaran Bruen 2017-03-27 09:02:56

vous devez le faire comme ceci pour l'instant, je sais pas très efficace car vous ne voulez pas convertir l'objet que vous recevez de firebase.

    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
répondu kevinius 2017-03-01 20:14:56

changer le type de démo en tableau ou itérez votre objet et poussez vers un autre tableau

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

et de html:

<div *ngFor="obj of details">
  <p>{{obj.key}}</p>
  <p>{{obj.value}}</p>
  <p></p>
</div>
0
répondu Mohammad Reza Mrg 2018-07-16 16:00:44