How to iterate object keys using *ngFor?
Solution 1
Update
In 6.1.0-beta.1 KeyValuePipe
was introduced https://github.com/angular/angular/pull/24319
<div *ngFor="let item of {'b': 1, 'a': 1} | keyvalue">
{{ item.key }} - {{ item.value }}
</div>
Previous version
You could try something like this
export class ObjNgFor implements PipeTransform {
transform(value: any, args: any[] = null): any {
return Object.keys(value).map(key => Object.assign({ key }, value[key]));
}
}
And then on your template
<div *ngFor="let obj of objs | ObjNgFor">
{{obj.key}} - {{obj.description}}
</div>
Solution 2
Or instead of creating a pipe and passing an object to *ngFor, just pass Object.keys(MyObject)
to *ngFor. It returns the same as the pipe, but without the hassle.
On TypeScript file:
let list = Object.keys(MyObject); // good old javascript on the rescue
On template (html):
*ngFor="let item of list"
Solution 3
Just return the keys from the pipe instead of the values and then use the keys to access the values:
(let
instead of #
in the beta.17)
@Pipe({ name: 'ObjNgFor', pure: false })
export class ObjNgFor implements PipeTransform {
transform(value: any, args: any[] = null): any {
return Object.keys(value)//.map(key => value[key]);
}
}
@Component({
selector: 'my-app',
pipes: [ObjNgFor],
template: `
<h1>Hello</h1>
<div *ngFor="let key of objs | ObjNgFor">{{key}}:{{objs[key].description}}</div> `,
})
export class AppComponent {
objs = {
"propertyA":{
"description":"this is the propertyA",
"default":"sth"
},
"propertyB":{
"description":"this is the propertyB",
"default":"sth"
}
};
}
See also Select based on enum in Angular2
Solution 4
keys.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'keys' })
export class KeysPipe implements PipeTransform {
transform(obj: Object, args: any[] = null): any {
let array = [];
Object.keys(obj).forEach(key => {
array.push({
value: obj[key],
key: key
});
});
return array;
}
}
app.module.ts
import { KeysPipe } from './keys.pipe';
@NgModule({
declarations: [
...
KeysPipe
]
})
example.component.html
<elem *ngFor="let item of obj | keys" id="{{ item.key }}">
{{ item.value }}
</elem>
Comments
-
uksz over 3 years
I've been digging around, and found out that I can use the following to use *ngFor over an object:
<div *ngFor="#obj of objs | ObjNgFor">...</div>
where
ObjNgFor
pipe is:@Pipe({ name: 'ObjNgFor', pure: false }) export class ObjNgFor implements PipeTransform { transform(value: any, args: any[] = null): any { return Object.keys(value).map(key => value[key]); } }
However, when I have an object like this:
{ "propertyA":{ "description":"this is the propertyA", "default":"sth" }, "propertyB":{ "description":"this is the propertyB", "default":"sth" } }
I am not quite sure how I can extract 'propertyA' and 'propertyB', so that it is accessible from the *ngFor directive. Any ideas?
UPDATE
What I want to do, is to present the following HTML:
<div *ngFor="#obj of objs | ObjNgFor" class="parameters-container"> <div class="parameter-desc"> {{SOMETHING}}:{{obj.description}} </div> </div>
Where something would be equal to
propertyA
andpropertyB
(this is how the object is structured). So, this would lead to:propertyA:this is the propertyA propertyB:this is the propertyB
-
uksz almost 8 yearsGunter - I would like to show user either 'propertyA' or 'propertyB'. So I need to change the pipe somehow
-
Günter Zöchbauer almost 8 yearsNot sure what you mean by that. Depending no what criteria do you want to show one or the other?
-
Günter Zöchbauer almost 8 yearsNot sure what exact use case you have in mind but I don't see why anything would not work with nested objects.
-
sabithpocker almost 7 yearsCan this be coupled with
async
pipe ifobjs
is asynchronous? -
Günter Zöchbauer almost 7 yearsSure
{{someObservable | async | ObjNgFor}}
-
leotesta over 6 years@GünterZöchbauer how I can access to object value in asynchronous case with this approach ?
-
Gaspa79 almost 6 yearsThank you!!! This made it look simple. You should add what to put on the template part btw =)
-
Willem de Jong almost 6 yearsneat solution. I got the number values and the string values in the list though so I used the slice method to get the proper side of the array: options.slice(options.length / 2). Found this solution here: stackoverflow.com/questions/38554562/…
-
ideeps over 5 yearsThe key value pipe is sorting out by the order of the keys and values orders in angular 6. How can we disable that ?
-
zmag over 4 yearsComplete code would be helpful instead of part of it.