访问键和使用* ngFor的对象的值

如何在angular2中获取对象的Key and Value的时候感到困惑,而用于迭代对象的时候会感到困惑。 我知道在角1.x有语法

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

但在角2我不知道我累了,但没有成功。 我已经尝试了下面的代码,但没有运行,请告诉我在哪里做错了。

 <ul> <li *ngFor='#key of demo'>{{key}}</li> </ul> demo = { 'key1': [{'key11':'value11'}, {'key12':'value12'}], 'key2': [{'key21':'value21'}, {'key22':'value22'}], } 

这里是plnkr我曾尝试过的相同: http ://plnkr.co/edit/mIj619FncOpfdwrR0KeG?p=preview

我想使用* ngFor动态获取key1key2 。 如何得到它? 我搜查了很多使用管道发现的想法,但如何使用我不知道。 有没有在angular2做同样的任何inbuild管道?

您可以创建一个自定义管道来返回每个元素的键列表。 类似的东西:

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

并像这样使用它:

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

编辑

您也可以返回包含键和值的条目:

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

并像这样使用它:

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

在模板中可以访问Object.keys ,并在*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(){} } 

用例子来阐述@ Thierry的回答。

没有内置的管道或方法从* ngFor循环获取key and value 。 所以我们必须为此创建自定义管道。 正如thierry所说,这是代码的答案。

** Pipe类实现了PipeTransform接口的transform方法,该方法接受一个输入值和一个可选的参数字符串数组,并返回转换后的值。

**变换方法对于管道是必不可少的。 PipeTransform接口定义了该方法并指导了工具和编译器。 这是可选的; 无论角度如何查找并执行变换方法。 欲了解更多信息关于管这里参考

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

和HTML部分是:

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

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

更新到RC

如user6123723建议(谢谢)在这里的评论是更新。

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

@Marton 对于接受的答案有一个重要的反对意见,理由是管道在每次变更检测时创建一个新的收集。 我会创建一个HtmlService,它提供了视图可以使用的一系列实用函数:

 @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(), you'll think of others... } 

如果你已经使用Lodash,你可以做这个简单的方法,包括键和值:

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

在打字稿文件中,包括:

 import * as _ from 'lodash'; 

并在导出的组件中包括:

 _: any = _; 

感谢管道,但我不得不做一些改变,然后我可以在角度2 RC5中使用它。 更改了管道导入行,并添加了任何类型的键数组初始化。

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

有一个真正好的图书馆,在其他好的管道之间做到这一点。 这就是所谓的ngx管道 。

例如,键管道返回对象的键,值管道返回对象的值:

键管道

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

值管道

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

不需要创建自己的定制管道:)

这是简单的解决方案

你可以使用typecript迭代器来做到这一点

 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

这里没有任何答案为我开箱,这是什么为我工作:

用内容创建pipes/keys.ts

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

添加到app.module.ts (您的主要模块):

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

然后添加到你的模块声明数组像这样:

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

然后在你的视图模板中,你可以使用这样的东西:

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

如果您想要阅读更多内容,请点击这里查看。

我认为Object.keys是解决这个问题的最好方法。 对于任何遇到这个问题的人来说,试图找出Object.keys为什么给他们['0','1']而不是['key1','key2'],这是一个警示故事 – 要小心“ of“和”in“:

我已经在使用Object.keys,类似这样的:

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

但是,而不是

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

我无意中写道

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

哪个“工作”完美没有任何错误,并返回

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

这花了我大约2个小时的谷歌搜索和诅咒..

(拍额头)

另一种方法是创建NgForIn指令,将使用像

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

Plunker例子

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

你必须这样做,现在我知道不是很有效,因为你不想转换你从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; });