0

I am pretty new to Javascript and Typescript/Angular..

I am getting data / game stats from a website to make my own stats app. I have created an Interface with defined Key/Values to match the data that I want to show on my template.

The API's response that I wish to show is in the form of nested objects. Because of this, I am using Object.keys() in order to iterate through the objects, and show the result on my HTML template.

I am able to show JSON of the specific nested Object just fine. My problem is: it is showing the ENTIRE Key/Values of that Object, and not the specific key values I have defined in my Interface.

Within my HTML, I am looping through my Interface called lifeTimeStat Object.keys(lifeTimeStat) - (also please see below for full html)

Seeing as how I need to iterate through an Object, I attempted to make my lifeTimeStat Interface an object.. Like this:

`export class CombatListComponent implements OnInit {

constructor(public combatService: CombatService) { }

lifeTimeStats: lifeTimeStat = {
headshotKills: null,
             kills: null,
             longestKill: null, 
             maxKillStreaks: null,
             dailyKills: null,
             weeklyKills: null,
             damageDealt: null,
             roadKills: null,
             teamKills: null,
              vehicleDestroys: null,
              suicides: null,
              roundMostKills: null,
              dBNOs: null,
              assists: null
  } 


ngOnInit() {
this.combatService.getCombat().subscribe(data => {this.lifeTimeStats = 
data} );  
}
}

`

But of course, however, I am getting this error: TypeError: Cannot read property 'keys' of undefined .. So it seems I am not making my Interface into an Object the right way..

The only way that I can get the JSON to show in my HTML is if I instead define Object = Object instead of that crappy attempt of turning my Interface into an object.. Argh. Object = Object will just show the entire Object and not the specific shape of my Interface..

HTML: combat-list.component.html <div *ngFor="let key of Object.keys(lifeTimeStat)"> {{ lifeTimeStats[key].attributes.gameModeStats.solo| json }} </div> <br>

Service Component: combat.service.ts

`@Injectable({
  providedIn: 'root'
})
export class CombatService {
getCombat():Observable<lifeTimeStat> {

return this.http.get<lifeTimeStat>(this.configUrl,  { observe:'body',   
responseType: 'json', headers: getHeaders });    

}`

Interface:

    `export interface lifeTimeStat {


            headshotKills: number,
             kills: number,
             longestKill: number, 
             maxKillStreaks: number,
             dailyKills: number,
             weeklyKills: number,
             damageDealt: number,
             roadKills: number,
             teamKills: number,
              vehicleDestroys: number,
              suicides: number,
              roundMostKills: number,
              dBNOs: number,
              assists: number,



}  `

I just want to show the selected data as I have defined in my Interface. I've been googling / searching on SO for many hours over the course of two, almost three days :(

1 Answer 1

1

So this syntax should work:

Object
  .keys({ a: 1, b: 2 })
  .map(key => console.log(key));

If not, why don't you assign the array to a variable and iterate over the variable?

In any case, you can use this nice helper to preserve types and iterate over both keys and values:

const testObject = {
  completed: true,
  score: 129.1,
  description: 'none',
};

entries(testObject)
 .map(([key, value]) => console.log(`Key is ${key}, value is ${value}`));

function entries<K>(object: K)  {
    return (Object.keys(object) as (keyof K)[])
        .filter((key) => object[key] !== undefined && object[key] !== null)
        .map(
            key => ([
                key,
                object[key],
            ] as [keyof K, Required<K>[keyof K]]),
    );
}

type Required<T> = {
    [P in keyof T]-?: T[P];
};

Or for your case:

const keyValuePairs = entries(lifeTimeStat);

...

<div *ngFor="const [key, value] of keyValuePairs">    {{ value.attributes.gameModeStats.solo| json }}  </div> <br>

Sign up to request clarification or add additional context in comments.

1 Comment

Interesting, I will try this and come back. Thanks a lot :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.