我对使用key
迭代对象时如何获取angular2中对象的value
和*ngFor
感到困惑。我知道在角度1.x中有一个类似
ng-repeat="(key, value) in demo"
但我不知道如何在angular2中做同样的事情。我尝试了类似的东西,没有成功:
<ul>
<li *ngFor='#key of demo'>{{key}}</li>
</ul>
demo = {
'key1': [{'key11':'value11'}, {'key12':'value12'}],
'key2': [{'key21':'value21'}, {'key22':'value22'}],
}
这是我尝试的一个方面: http://plnkr.co/edit/mIj619FncOpfdwrR0KeG?p=preview
如何使用key1
动态获取key2
和*ngFor
?在广泛搜索之后,我发现了使用管道的想法,但我不知道如何去做。
是否有任何内置管道在angular2中做同样的事情?
答案 0 :(得分:298)
在模板中可以访问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(){}
}
答案 1 :(得分:203)
您可以创建自定义管道以返回每个元素的键列表。 这样的事情:
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="let c of content">
<td *ngFor="let 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="let entry of content | keys">
Key: {{entry.key}}, value: {{entry.value}}
</span>
答案 2 :(得分:162)
与最新版本的Angular(v6.1.0)一样,Angular Team为keyvalue
管道添加了新的内置管道,以帮助您遍历对象,地图,和数组,位于angular包的common
模块中。
例如-
<div *ngFor="let item of testObject | keyvalue">
Key: <b>{{item.key}}</b> and Value: <b>{{item.value}}</b>
</div>
在此处查看更多有用的信息-
如果您使用的是Angular v5或更低版本,或者您想要使用管道来实现,请遵循以下答案
答案 3 :(得分:35)
在 6.1.0-beta.1 KeyValuePipe 中引入了https://github.com/angular/angular/pull/24319
<div *ngFor="let item of {'b': 1, 'a': 1} | keyvalue">
{{ item.key }} - {{ item.value }}
</div>
<强> Plunker Example 强>
另一种方法是创建将使用的NgForIn
指令,如:
<div *ngFor="let key in obj">
<b>{{ key }}</b>: {{ obj[key] }}
</div>
<强> Plunker Example 强>
<强> 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);
}
}
}
答案 4 :(得分:23)
以示例的方式阐述@ Thierry的答案。
没有内置管道或方法从* ngFor循环中获取key and value
。所以我们必须为它创建自定义管道。正如蒂埃里所说,这是代码的答案。
**管道类实现了PipeTransform接口的转换方法,该方法接受输入值和可选的参数字符串数组并返回转换后的值。
**转换方法对管道至关重要。 PipeTransform接口定义该方法并指导工具和编译器。它是可选的;无论如何,Angular会查找并执行转换方法。 有关管道refer here
的更多信息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
正如user6123723(感谢)在评论中所建议的那样是更新。
<ul>
<li *ngFor='let key of demo | keys'>
Key: {{key.key}}, value: {{key.value}}
</li>
</ul>
答案 5 :(得分:21)
在Angular 6.1中,您可以使用 keyvalue 管道:
<div *ngFor="let item of testObject | keyvalue">
Key: <b>{{item.key}}</b> and Value: <b>{{item.value}}</b>
</div>
但是它不方便按键值对结果列表进行排序。 如果您需要中立的东西:
@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;
}
}
不要忘记指定 pure:false 管道属性。在这种情况下,即使输入引用未更改(在向对象添加属性时也是如此),管道在每个更改检测周期被调用。
答案 6 :(得分:18)
@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(), and others...
}
答案 7 :(得分:15)
如果你已经在使用Lodash,你可以采用这种简单的方法,包括密钥和价值:
<ul>
<li *ngFor='let key of _.keys(demo)'>{{key}}: {{demo[key]}}</li>
</ul>
在打字稿文件中,包括:
import * as _ from 'lodash';
并在导出的组件中包含:
_: any = _;
答案 8 :(得分:8)
感谢管道,但我必须做一些更改才能在角度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;
}
}
答案 9 :(得分:6)
要为Angular 8添加答案:
对于循环,您可以执行以下操作:
<ng-container *ngFor="let item of BATCH_FILE_HEADERS | keyvalue: keepOriginalOrder">
<th nxHeaderCell>{{'upload.bulk.headings.'+item.key |translate}}</th>
</ng-container>
如果您还需要上述数组来保持原始顺序,请在您的类中声明以下内容:
public keepOriginalOrder = (a, b) => a.key;
答案 10 :(得分:6)
有一个非常好的库可以在其他漂亮的管道中执行此操作。它被称为ngx-pipes。
例如,keys管道返回对象的键,值管道返回对象的值:
键管
<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 -->
无需创建自己的自定义管道:)
答案 11 :(得分:6)
这里没有任何答案对我有用,这对我有用:
使用内容创建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>
如果你想阅读更多内容,Here是一个很好的参考。
答案 12 :(得分:3)
这是简单的解决方案
您可以为此
使用typescript迭代器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]
}
}
}
};
}
}
答案 13 :(得分:2)
将演示类型更改为数组 或遍历对象并推送到另一个数组
id_token
并来自html:
public details =[];
Object.keys(demo).forEach(key => {
this.details.push({"key":key,"value":demo[key]);
});
答案 14 :(得分:1)
我认为Object.keys是解决这个问题的最佳方法。对于任何遇到这个答案的人,并试图找出为什么Object.keys给他们['0','1']而不是['key1','key2'],这是一个警示故事 - 要注意“ “和”中的“和”:
我已经在使用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个小时的谷歌搜索和诅咒..
(拍前额)
答案 15 :(得分:1)
您可以通过动态对象的键
myObj['key']
答案 16 :(得分:1)
使用索引:
<div *ngFor="let value of Objects; index as key">
用法:
{{key}} -> {{value}}
答案 17 :(得分:0)
你现在必须这样做,我知道效率不高,因为你不想转换你从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;
});