I am trying to iterate over the properties of an object using *ngFor
but using in
. When I try to do this
@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}
}
I get the error message:
Can't bind to 'ngForIn' since it isn't a known property of 'li'.
I have included FormsModule
and BrowserModule
in the imports
section of the @NgModule
for this component.
Is it possible to use ngForIn
on li
and if not is there an idiomatic alternative?
As AJT_82 mentioned in comment you can create special directive for such purposes. It will be based on NgForOf<T>
directive:
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
The easiest approach would be to turn your object into an array using Object.values()
and Object.keys()
. Check out this plunker for an example.
If you want access to the keys as well as the value you can include an index in your *ngFor
.
Template:
<ul>
<li *ngFor="let item of array; let index = index;">
<b>{{keys[index]}}</b> value: {{item}}, index: {{index}}
</li>
</ul>
Component 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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With