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 ?
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(){}
}
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>
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 -
- https://github.com/angular/angular/blob/master/CHANGELOG.md#features-3
- https://github.com/angular/angular/commit/2b49bf7
si vous utilisez un angle v5 ou inférieur ou si vous voulez utiliser un tuyau, suivez cette réponse
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>
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>
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);
}
}
}
é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>
@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...
}
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 = _;
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;
}
}
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;
}
}
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.
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:)
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]
}
}
}
};
}
}
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)
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;
});
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>