angular 4 中可以使用 ngForIn 吗?
Can ngForIn be used in angular 4?
我正在尝试使用 *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}
}
我收到错误消息:
Can't bind to 'ngForIn' since it isn't a known property of 'li'.
我已将 FormsModule
和 BrowserModule
包含在该组件的 @NgModule
的 imports
部分中。
是否可以在 li
上使用 ngForIn
,如果不能,是否有惯用的替代方法?
最简单的方法是使用 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>
组件打字稿:
export class App {
obj = {a: 1, b: 2}
array = [];
keys = [];
constructor() {
}
ngOnInit() {
this.array = Object.values(this.obj);
this.keys = Object.keys(this.obj);
}
}
正如评论中提到的 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);
}
}
}
Object.keys
和 Object.values
可以分配给组件上的 public 属性,然后它们可以作为模板中的函数使用。例如
//somewhere in the component
public objectKeys = Object.keys;
public objectValues = Object.values;
//somewhere in template
...*ngFor="let key of objectKeys(someObject)"...
事情发生了一些变化(在 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;
}
}
}
我正在尝试使用 *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}
}
我收到错误消息:
Can't bind to 'ngForIn' since it isn't a known property of 'li'.
我已将 FormsModule
和 BrowserModule
包含在该组件的 @NgModule
的 imports
部分中。
是否可以在 li
上使用 ngForIn
,如果不能,是否有惯用的替代方法?
最简单的方法是使用 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>
组件打字稿:
export class App {
obj = {a: 1, b: 2}
array = [];
keys = [];
constructor() {
}
ngOnInit() {
this.array = Object.values(this.obj);
this.keys = Object.keys(this.obj);
}
}
正如评论中提到的 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);
}
}
}
Object.keys
和 Object.values
可以分配给组件上的 public 属性,然后它们可以作为模板中的函数使用。例如
//somewhere in the component
public objectKeys = Object.keys;
public objectValues = Object.values;
//somewhere in template
...*ngFor="let key of objectKeys(someObject)"...
事情发生了一些变化(在 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;
}
}
}