我正在尝试使用*ngFor
但使用in
来迭代对象的属性。当我尝试这样做时
@Controller({
selector: 'sample-controller',
template: `
<ul>
<li *ngFor="let i in obj">
<b>{{i}}</b>: {{obj[i]}}
</li>
</ul>`
})
class SampleController {
obj = {a: 1, b: 2}
}
我收到错误消息:
无法绑定到'ngForIn',因为它不是'li'的已知属性。
我已在FormsModule
的{{1}}部分中为此组件添加了BrowserModule
和imports
。
是否可以在@NgModule
上使用ngForIn
,如果没有,是否有惯用的选择?
答案 0 :(得分:7)
正如评论中提到的AJT_82,您可以为此目的创建特殊指令。它将基于NgForOf<T>
指令:
interface NgForInChanges extends SimpleChanges {
ngForIn?: SimpleChange;
ngForOf?: SimpleChange;
}
@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);
}
}
}
<强> Plunker Example 强>
答案 1 :(得分:3)
最简单的方法是使用Object.values()
和Object.keys()
将对象转换为数组。查看this plunker以获取示例。
如果您想要访问密钥和值,可以在*ngFor
中添加索引。
<强>模板:强>
<ul>
<li *ngFor="let item of array; let index = index;">
<b>{{keys[index]}}</b> value: {{item}}, index: {{index}}
</li>
</ul>
组件TypeScript:
export class App {
obj = {a: 1, b: 2}
array = [];
keys = [];
constructor() {
}
ngOnInit() {
this.array = Object.values(this.obj);
this.keys = Object.keys(this.obj);
}
}
答案 2 :(得分:1)
事情已经发生了一些变化(在Angular 9中),所以yurzi的答案将行不通,但是在类似的行上,将'forOf'的值设置为'super.ngForOf'可以解决问题
import { ContentChildren, Directive, Input, IterableDiffers, NgIterable, OnChanges, SimpleChanges, TemplateRef, ViewChildren, ViewContainerRef } from "@angular/core";
import { NgForOf } from "@angular/common";
export interface Selectable<T> { selected: boolean; isActive: boolean; }
@Directive({
selector: "[optionsFor][[optionsForOf]]" })
export class OptionsForDirective<T extends Selectable<any>,U extends NgIterable<T> = NgIterable<T>>
extends NgForOf<T, U> implements OnChanges {
_editMode = false;
_forOf: Array<Selectable<any>>;
@Input()
set iefOptionsForOf(value: any) {
this._forOf = value;
console.log("set of: ", value);
}
@Input()
set iefOptionsForEditMode(value: boolean) {
this._editMode = value;
console.log("set edit mode: ", value);
}
constructor(
public _viewContainer2: ViewContainerRef,
public _templateRef2: TemplateRef<any>,
public _differs2: IterableDiffers ) {
super(_viewContainer2, _templateRef2, _differs2);
}
ngOnChanges(changes: SimpleChanges) {
if (changes.optionsForOf) {
const origNgForOf: Array<Selectable<any>> = this._forOf;
let filtered = origNgForOf;
if (origNgForOf) {
filtered = origNgForOf.filter(s => {
return this._editMode || s.isActive !== false;
});
}
console.log("filtered", filtered);
super.ngForOf = filtered as any;
}
}
}
答案 3 :(得分:0)
Object.keys
和Object.values
分配给组件上的公共属性,然后将它们用作模板中的函数。例如
//somewhere in the component
public objectKeys = Object.keys;
public objectValues = Object.values;
//somewhere in template
...*ngFor="let key of objectKeys(someObject)"...