666

I am a bit confused about how to get the key and value of an object in angular2 while using *ngFor for iterating over the object. I know in angular 1.x there is a syntax like

ng-repeat="(key, value) in demo"

but I don't know how to do the same in angular2. I have tried something similar, without success:

    <ul>
      <li *ngFor='#key of demo'>{{key}}</li>
    </ul>

    demo = {
        'key1': [{'key11':'value11'}, {'key12':'value12'}],
        'key2': [{'key21':'value21'}, {'key22':'value22'}],
      }

Here is a plnkr with my attempt: http://plnkr.co/edit/mIj619FncOpfdwrR0KeG?p=preview

How can I get key1 and key2 dynamically using *ngFor? After searching extensively, I found the idea of using pipes but I don't know how to go about it. Is there any inbuilt pipe for doing the same in angular2?

Syntle
  • 5,168
  • 3
  • 13
  • 34
Pardeep Jain
  • 84,110
  • 37
  • 165
  • 215

21 Answers21

818

As in latest release of Angular (v6.1.0) , Angular Team has added new built in pipe for the same named as keyvalue pipe to help you iterate through objects, maps, and arrays, in the common module of angular package. For example -

<div *ngFor="let item of testObject | keyvalue">
    Key: <b>{{item.key}}</b> and Value: <b>{{item.value}}</b>
</div>

To keep original order, use keyvalue:onCompare,
and in component define callback:

// ...
import {KeyValue} from '@angular/common';

@Component(/* ... */)
export class MyComponent {
  private onCompare(_left: KeyValue<any, any>, _right: KeyValue<any, any>): number {
    return -1;
  }
}

Working Forked Example

check it out here for more useful information -

If you are using Angular v5 or below or you want to achieve using pipe follow this answer

Top-Master
  • 7,611
  • 5
  • 39
  • 71
Pardeep Jain
  • 84,110
  • 37
  • 165
  • 215
  • 3
    lol I had to do an ng6 update just to access this pipe - great stuff - thx – danday74 Aug 06 '18 at 16:44
  • 71
    You can keep the original key order using a custom comparator: `*ngFor="let item of testObject | keyvalue:keepOriginalOrder"` and in your class define: `public keepOriginalOrder = (a, b) => a.key` – mike-shtil Aug 22 '18 at 15:32
  • 1
    this should be the answer - working well on angular 7 – calios Mar 12 '19 at 15:31
  • So the reason I'm here is because Canada decided to give their Provinces with two-letter abbreviations and the written order vs Province abbreviation for Northwest Territories (NT) and Nova Scotia (NS) don't line up. "Nor" comes before "Nov", but NS comes before NT. – Robbie Smith Jan 09 '21 at 06:12
  • hi @PardeepJain do you have an answer for this one? https://stackoverflow.com/questions/66395350/angular-keyvalue-pipe-not-working-on-string-number-enum –  Feb 27 '21 at 03:38
  • 1
    @mike-shtil that comment was lit! thanks man that is exactly what I needed but worried if it is impacting performance as looping twice – minigeek Mar 31 '21 at 19:02
  • For simple : https://plnkr.co/edit/fTh6zerwbf06EhdZ?open=lib%2Fapp.ts&deferRun=1 – 3gwebtrain Sep 27 '21 at 07:06
  • 1
    What if {{item.value}} is again object? How to access its values? – pera May 24 '22 at 22:48
  • this answer work on angular 13, thank you – ilham doang Oct 04 '22 at 09:02
450

Have Object.keys accessible in the template and use it in *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(){}
}
tomtastico
  • 6,136
  • 2
  • 23
  • 28
  • 1
    @PardeepJain it's an ES5 method https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys – tomtastico Mar 15 '17 at 19:15
  • 1
    @tomtastico How would you display this for a 3D array? For example {"1": {"1.1": ["1.1.1","1.1.2"]}}. And then nesting 3 ngFor's – Frank Mar 26 '18 at 07:09
  • @Frank you just said it yourself. Nest the `*ngFor`s. First two using `objectKeys`, innermost no need (as it's just an array). – tomtastico Mar 26 '18 at 21:56
  • Though [recall](https://stackoverflow.com/a/31537666/1028230): "*Maps have no orders in keys and hence their iteration is unpredictable.*" You should probably sort the keys in `objectKeys` to make the sticklers happy. ;^) Pretty sure the [new pipe](https://github.com/angular/angular/pull/24319) does. – ruffin Jul 20 '18 at 13:30
  • 1
    Awesome. Setting objectKeys = Object.keys is simplest method I've seen to be able to check the length of an object from the HTML. – JAC Aug 02 '18 at 15:49
  • While it works, I get this error in Visual Code: "Member 'objectKeys' is not callable Angular" – Jonathan Oct 21 '19 at 01:05
245

You could create a custom pipe to return the list of key for each element. Something like that:

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;
  }
}

and use it like that:

<tr *ngFor="let c of content">           
  <td *ngFor="let key of c | keys">{{key}}: {{c[key]}}</td>
</tr>

Edit

You could also return an entry containing both key and value:

@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;
  }
}

and use it like that:

<span *ngFor="let entry of content | keys">           
  Key: {{entry.key}}, value: {{entry.value}}
</span>
Muhammad Shaharyar
  • 1,044
  • 1
  • 8
  • 23
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • What do you mean regarding async? Perhaps its use in my answer is ambiguous. The pipe doesn't need it. You can use pipe if the object you want to iterate over is an observable... – Thierry Templier Feb 21 '16 at 16:57
  • Thanks! Also, Good explanation here, check this - How to use Pipes! https://medium.com/front-end-hacking/angular-2-let-s-talk-about-pipes-ng-filter-in-angular-1-f46319edaf73#.fw9qvebjv – Ankit Maheshwari Aug 25 '16 at 13:43
  • 1
    note the missing closing bracket in `keys.push({key: key, value: value[key]);` – golyo Sep 08 '16 at 10:16
  • 58
    I actually discourage anyone from using pipes to create collections inside `*ngFor` expression. It creates huge performance bottleneck because it needs to generate the collection every time the change detector checks for changes. – martin Sep 11 '16 at 10:38
  • 3
    Thanks for the solution...the problem is that whenever the object changes, the pipe doesn't update. If I add `pure:false` to the pipe, it becomes very inefficient. Do you have a solution to update the pipe manually whenever I change the object (remove item)? – Nate May 03 '17 at 15:06
  • Lovely answer Thierry. What changes do I need to make to make it work for an `object array` like [{"animal":"dog", "country":"france", "car":"nano"}] – Aakash Thakur May 25 '17 at 19:19
  • Thanks! You can add a first `ngFor` to iterate over the array and put the `ngFor` with the pipe in it... Hope it answers your question! – Thierry Templier May 29 '17 at 06:47
  • 4
    The answer is a little bit outdated. The line *ngFor="#entry of content | keys" doesn't work properly and the for ... in loop better to change to "for (const key of Object.keys(value)) " – Experimenter Sep 13 '17 at 10:29
  • `ngFor` has been removed. Need to change to `ngForOf`. ` {{c}} ` – Rach Chen Nov 02 '17 at 03:15
  • 2
    @RachChen Not in templates: `common: NgFor has been removed as it was deprecated since v4. Use NgForOf instead. This does not impact the use of*ngFor in your templates.` (https://jaxenter.com/road-to-angular-5-133253.html) – mwld Nov 16 '17 at 12:21
  • 1
    @martin Would that actually be such a performance loss when using just `Object.keys()` to retrieve the keys within the pipe? – mwld Nov 16 '17 at 12:32
  • You should use keys.unshift(...) instead of keys.push(...), this will preserve the order of the keys in the loop. – klonq Apr 15 '18 at 13:59
68

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>

Plunker Example

Previous version

Another approach is to create NgForIn directive that will be used like:

<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);
    }
  }
}
yurzui
  • 205,937
  • 32
  • 433
  • 399
52

From Angular 6.1 you can use the keyvalue pipe:

<div *ngFor="let item of testObject | keyvalue">
    Key: <b>{{item.key}}</b> and Value: <b>{{item.value}}</b>
</div>

But it has the inconvenient that sorts the resulting list by the key value. If you need something neutral:

@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;
  }
}

Don't forget to specify the pure:false pipe attribute. In this case, the pipe is invoked on each change-detection cycle, even if the input reference has not changed (so is the case when you add properties to an object).

Gerard Carbó
  • 1,775
  • 18
  • 16
  • Already shared the same answer above https://stackoverflow.com/a/51491848/5043867 – Pardeep Jain Aug 19 '18 at 14:25
  • @PardeepJain please let other people share as well :) ! second part of answer is what I needed – minigeek Mar 31 '21 at 18:58
  • @minigeek different solutions are always welcome mate. But when I have posted the comment this second part you referring was missing and only first part is there which is duplucate of accepted answer. you can check changelog of answer history. – Pardeep Jain Apr 01 '21 at 04:39
  • 1
    @PardeepJain. Yes your answer and that guy's comment only helped me fix thing. I understand ur point how plagiarism feels :p – minigeek Apr 01 '21 at 04:50
28

Elaboration of @Thierry's answer with example.

There is no inbuilt pipe or method to get key and value from the *ngFor loop. so we have to create custom pipe for the same. as thierry said here is the answer with code.

** The pipe class implements the PipeTransform interface's transform method that takes an input value and an optional array of parameter strings and returns the transformed value.

** The transform method is essential to a pipe. The PipeTransform interface defines that method and guides both tooling and the compiler. It is optional; Angular looks for and executes the transform method regardless. for more info regards pipe 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;
  }
}

and HTML part is:

<ul>
  <li *ngFor='#key of demo | keys'>
   Key: {{key.key}}, value: {{key.value}}
  </li>
</ul>

Working Plnkr http://plnkr.co/edit/50LlK0k6OnMnkc2kNHM2?p=preview

update to RC

as suggested by user6123723(thanks) in comment here is update.

<ul>
  <li *ngFor='let key of demo | keys'>
   Key: {{key.key}}, value: {{key.value}}
  </li>
</ul>
Community
  • 1
  • 1
Pardeep Jain
  • 84,110
  • 37
  • 165
  • 215
  • This needs to be updated: Here's the warning I get "#" inside of expressions is deprecated. Use "let" instead! (" -->
    • ]*ngFor='#key of demo| keys'> Key: {{key.key}}, value: {{key.value}}
    • "): myComponent@56:6
    – user6123723 Aug 21 '16 at 00:43
  • Not sure if this is new, but to cite from the docs: > We must include our pipe in the declarations array of the AppModule. – Akzidenzgrotesk Sep 10 '16 at 11:52
20

@Marton had an important objection to the accepted answer on the grounds that the pipe creates a new collection on each change detection. I would instead create an HtmlService which provides a range of utility functions which the view can use as follows:

@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...
}
Stephen Paul
  • 37,253
  • 15
  • 92
  • 74
  • 2
    and how is that better than just `Object.keys(...)` inside the *ngFor? – Simon_Weaver Dec 15 '16 at 02:32
  • 8
    Because it will throw: `TypeError: Cannot read property 'keys' of undefined`. It doesn't seem to be supported in the template. – Stephen Paul Dec 15 '16 at 05:39
  • 1
    This works very well as a solution and avoids the performance issues pointed out above. http://stackoverflow.com/questions/35534959/access-key-and-value-of-object-using-ngfor/39896058#comment66192984_35536052 – J. Adam Connor Jan 18 '17 at 04:23
  • hello, can this b used not in the `template` option, but in the template's actual html code? thanks – Scaramouche Aug 25 '19 at 03:05
18

If you're already using Lodash, you can do this simple approach which includes both key and value:

<ul>
  <li *ngFor='let key of _.keys(demo)'>{{key}}: {{demo[key]}}</li>
</ul>

In the typescript file, include:

import * as _ from 'lodash';

and in the exported component, include:

_: any = _;
Jeremy Moritz
  • 13,864
  • 7
  • 39
  • 43
13

Thought of adding an answer for Angular 8:

For looping you can do:

<ng-container *ngFor="let item of BATCH_FILE_HEADERS | keyvalue: keepOriginalOrder">
   <th nxHeaderCell>{{'upload.bulk.headings.'+item.key |translate}}</th>
</ng-container>

Also if you need the above array to keep the original order then declare this inside your class:

public keepOriginalOrder = (a, b) => a.key;
Juliyanage Silva
  • 2,529
  • 1
  • 21
  • 33
10

Thanks for the pipe but i had to make some changes before i could use it in angular 2 RC5. Changed the Pipe import line and also added type of any to the keys array initialization.

 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;
  }
}
Winnipass
  • 904
  • 11
  • 22
8

You can use the keyvalue pipe as the sample code is provided:

    <div style="flex-direction: column">
        <app-cart-item
            class="cart-item"
            *ngFor="let keyValuePair of this.allProductRecords | keyvalue"
            [productRecord]="keyValuePair.value"
            (removeProduct)="removeProductFromCart(keyValuePair.key)"
        ></app-cart-item>
        <br />
        <p style="font-family: Verdana, Geneva, Tahoma, sans-serif; font-weight: bolder">
            Total ${{ getTotalPurchaseAmount() }}
        </p>
    </div>
Arefe
  • 11,321
  • 18
  • 114
  • 168
7

None of the answers here worked for me out of the box, here is what worked for me:

Create pipes/keys.ts with contents:

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;
    }
}

Add to app.module.ts (Your main module):

import { KeysPipe } from './pipes/keys';

and then add to your module declarations array something like this:

@NgModule({
    declarations: [
        KeysPipe
    ]
})
export class AppModule {}

Then in your view template you can use something like this:

<option *ngFor="let entry of (myData | keys)" value="{{ entry.key }}">{{ entry.value }}</option>

Here is a good reference I found if you want to read more.

cjohansson
  • 1,058
  • 10
  • 13
  • may i know what is the difference betwee your answer and other answer's (using pipe only) provided above ? it seems same as above – Pardeep Jain May 18 '17 at 10:52
  • 1
    Sure 1. The examples above uses *ngFor="#entry" instead of *ngFor="let entry of" and my compiler didn't accept the #entry syntax, the reference doesn't use # either. "let entry of (myData | keys)" seems to be a better solution. 2. My compiler didn't validate the example Pipe Class either because it was missing explicit data types so I added that. 3. The examples above doesn't show how to integrate the Pipe into a project which my answer does, you need to import it into the main module. – cjohansson May 18 '17 at 11:48
  • haha yes offcourese, because when answer was given at that time syntax including `#` etc. btw your answer is also correct no doubt – Pardeep Jain May 18 '17 at 12:03
7

Use index:

<div *ngFor="let value of Objects; index as key">

Usage:

{{key}} -> {{value}}
Adonias Vasquez
  • 1,014
  • 13
  • 11
  • 2
    That is something new to me, Better If you could add example along with your answer :) Also can you point me to any documentation for the same? – Pardeep Jain Apr 30 '19 at 16:50
  • 1
    What is the type of Objects ? Array or Map? Please make it clear. Thanks in advance – Basil Apr 18 '20 at 18:51
  • 2
    In this example, the "key" is the index. This have nothing to do with the question and wont work to access the real key – Raphaël Balet Jan 07 '21 at 14:36
6

There's a real nice library that does this among other nice pipes. It's called ngx-pipes.

For example, keys pipe returns keys for an object, and values pipe returns values for an object:

keys pipe

<div *ngFor="let key of {foo: 1, bar: 2} | keys">{{key}}</div> 
<!-- Output: 'foo' and 'bar -->

values pipe

<div *ngFor="let value of {foo: 1, bar: 2} | values">{{value}}</div>
<!-- Output: 1 and 2 -->

No need to create your own custom pipe :)

RichieRock
  • 1,138
  • 1
  • 8
  • 13
  • 2
    good alternate, but thing is why to use external library for simple peace of code if we can do this using simple piece of code like pipe – Pardeep Jain May 22 '17 at 09:14
  • 2
    Umm... but it is a pipe? It's just one line in your package.json and another two lines in your module when you import the library. On the other hand, a custom pipe needs a separate file with some 10-20 lines of code and also the import lines in your module. We find using ngx-pipes very easy in our projects. Why should we reinvent the wheel? :) – RichieRock May 23 '17 at 12:17
  • yeah no doubt, actually its an opinion based, you can choose either between these two, no one is wrong way. – Pardeep Jain May 23 '17 at 12:26
  • 2
    Don't forget, if you write a custom pipe, you must test that custom pipe *as well*. So that's 10-20 lines of pipe code, and then probably 20-40 lines of test code to test the pipe. – danwellman Jan 23 '18 at 10:07
3

Here is the simple solution

You can use typescript iterators for this

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]
              }
            }
          }
    };
  }
}

http://plnkr.co/edit/GpmX8g?p=info

Sudheer KB
  • 1,596
  • 14
  • 28
3

change demo type to array or iterate over your object and push to another array

public details =[];   
Object.keys(demo).forEach(key => {
      this.details.push({"key":key,"value":demo[key]);
    });

and from html:

<div *ngFor="obj of details">
  <p>{{obj.key}}</p>
  <p>{{obj.value}}</p>
  <p></p>
</div>
Mohammad Reza Mrg
  • 1,552
  • 15
  • 30
3

ECMA 2017+ solution

Following the idea of some other answers, you can create a Pipe to create an array of [key, value] from your object, but in a much simpler way, following the new method Object.entries introduced in the ECMA 2017.

Pipe

import { PipeTransform, Pipe } from '@angular/core';

/**
 * Transform a literal object into array
 */
@Pipe({
  name: 'forObject',
  pure: true,
})
export class ForObjectPipe implements PipeTransform {

  transform(object, args?: any): any {
    return Object.entries(object);
  }
}

Module

In your module, you declare and provide it

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { ForObjectPipe } from './for-object.pipe';

import { MyPageRoutingModule } from './my-routing.module';
import { MyPage } from './my.page';

@NgModule({
  imports: [
    CommonModule,
    MyPageRoutingModule,
  ],
  declarations: [
    MyPage,
    ForObjectPipe,
  ],
  providers: [
    ForObjectPipe,
  ]
})
export class MyPageModule {}

Then you can use in your component typescript code or HTML.

Using in component

// ...
import { ForObjectPipe } from './for-object.pipe';

@Component({
  selector: 'app-my',
  templateUrl: './my.page.html',
  styleUrls: ['./my.page.scss'],
})
export class MyComponent {
  obj: { [key: any]: any } = {
    1: 'hello',
    2: 'world',
  };

  constructor(private forObjectPipe: ForObjectPipe) { }

  foo() {
     const myArray = this.forObjectPipe.transform(this.obj);
     // same as 
     const myArray = Object.entries(this.obj);
  }
}

Using in component view

<h1>Object:</h1>
<div *ngFor="let pair of obj | forObject">
  KEY: {{ pair[0] }} - VALUE: {{ pair[1] }}
</div>

Output:

Object:
KEY: 1 - VALUE: hello
KEY: 2 - VALUE: world

Live Demo: https://stackblitz.com/edit/angular-qapapx?file=src/app/hello.component.ts

Wesley Gonçalves
  • 1,985
  • 2
  • 19
  • 22
  • This does not answer the question! return Object.values(object); will give a list of values and not the key, values as asked. – Bill Jun 09 '22 at 09:42
  • Sorry, @Bill. I changed the method to return the key-value pair instead of only the values. Instead of using `Object.values`, you can use `Object.entries`. Thanks for pointing that out. – Wesley Gonçalves Jun 10 '22 at 01:42
2

I think Object.keys is the best solution to this problem. For anyone that comes across this answer and is trying to find out why Object.keys is giving them ['0', '1'] instead of ['key1', 'key2'], a cautionary tale - beware the difference between "of" and "in":

I was already using Object.keys, something similar to this:

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;
}

However, instead of

for (const key OF Object.keys(mydemo)) {

I had inadvertently wrote

for (const key IN Object.keys(mydemo)) {

which "worked" perfectly fine without any error and returned

[{key: '0', value: undefined}, {key: '1', value: undefined}]

That cost me about 2 hours googling and cursing..

(slaps forehead)

Ciarán Bruen
  • 5,221
  • 13
  • 59
  • 69
1

You have to do it like this for now, i know not very efficient as you don't want to convert the object you receive from 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;

    });
kevinius
  • 4,232
  • 7
  • 48
  • 79
0

you can get dynamic object's key with by trying this

myObj['key']
Rizwan
  • 3,741
  • 2
  • 25
  • 22
-3

Create your array like this

tags = [
        {
            name : 'Aliko Dogara',
            amount   : '60,000',
            purpose: 'Office repairs'
        },
        {
            name : 'Aliko Dogara',
            amount   : '60,000',
            purpose: 'Office repairs'
        },
        {
            name : 'Aliko Dogara',
            amount   : '60,000',
            purpose: 'Office repairs'
        },
        {
            name : 'Aliko Dogara',
            amount   : '60,000',
            purpose: 'Office repairs'
        },
        {
            name : 'Aliko Dogara',
            amount   : '60,000',
            purpose: 'Office repairs'
        }
    ];

works all the time