Hargun Suri
Hargun Suri

Reputation: 311

How to access JSON object value with dynamic key in typescript with angular

I want to access value present in JSON object with configurable targetPath for response received.

Below is my component class which will bind the data present in list to the autocomplete drop down in HTML code

the configurable key is 'path', which value I want to provide as a key in custom JSON object key 'field'.

import { Component, ViewChild } from '@angular/core';
import { MenuItem } from 'primeng/api';
import { SelectItem } from 'primeng/api';
import { SelectItemGroup } from 'primeng/api';
import { FilterService } from 'primeng/api';
import { AutoComplete } from 'primeng/autocomplete';
import { CountryService } from './countryservice';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  providers: [CountryService, FilterService]
})
export class AppComponent {
  userDetails: any[];

  selectedUserDetails: any[];

  selectedValue: any;

  selectedUserDetail: any;

  path: string = 'contactMedium[0].characteristic.emailAddress';

  testVal: string;

  constructor() {}

  ngOnInit() {
    this.userDetails = [
      {
        id: 'cont-609',
        contactMedium: [
          {
            characteristic: {
              emailAddress: '[email protected]'
            }
          }
        ]
      },
      {
        id: 'cont-610',
        contactMedium: [
          {
            characteristic: {
              emailAddress: '[email protected]'
            }
          }
        ]
      },
      {
        id: 'cont-611',
        contactMedium: [
          {
            characteristic: {
              emailAddress: '[email protected]'
            }
          }
        ]
      },
      {
        id: 'cont-612',
        contactMedium: [
          {
            characteristic: {
              emailAddress: '[email protected]'
            }
          }
        ]
      },
      {
        id: 'cont-614',
        contactMedium: [
          {
            characteristic: {
              emailAddress: '[email protected]'
            }
          }
        ]
      }
    ];
  }

  filterUserDetails(event) {
    const filteredNew: any[] = [];
    this.getUserDetails().then(response => {
      for (let resp of response) {
        this.testVal = resp[this.path];
        filteredNew.push({
          id: resp.id,
          field: resp[this.path]
        });
      }
    });

    this.selectedUserDetails = filteredNew;
  }

  getUserDetails(): Promise<any[]> {
    return Promise.resolve(this.userDetails);
  }

  chooseItem(event) {
    this.selectedUserDetail =
      event.contactMedium[0].characteristic.emailAddress;
  }
}

From the response received from method getUserDetails(), I am building a custom JSON object array with fields 'id' and 'field', the key for id is known which itself is a 'id' but key for field is configurable which is path in my case.

But looks like above logic where key is accessed is not working as expected i.e I am not getting value for

  filterUserDetails(event) {
    const filteredNew: any[] = [];
    this.getUserDetails().then(response => {
      for (let resp of response) {
        this.testVal = resp[this.path];
        filteredNew.push({
          id: resp.id,
          field: resp[this.path]
        });
      }
    });

    this.selectedUserDetails = filteredNew;
  }

Below is my HTML code

<h5>Dropdown Testing</h5>
<p>selectedUserDetail : {{selectedUserDetail}}</p>
<p>TestVal : {{testVal}}</p>
<p-autoComplete [(ngModel)]="selectedUserDetail" [suggestions]="selectedUserDetails"
  (completeMethod)="filterUserDetails($event)" [dropdown]="true" field="field">
  <ng-template let-userDetails pTemplate=" item">
    <div>{{userDetails.field}}</div>
  </ng-template>
</p-autoComplete>

If I change the usage of assignment like below everything works fine

field: resp.contactMedium[0].characteristic.emailAddress

Link of my code is here : https://stackblitz.com/edit/primeng-autocomplete-demo-dyihrs?file=src%2Fapp%2Fapp.component.html

Expectation here is to assign value of key: contactMedium[0].characteristic.emailAddress received from getUserDetails() to custom JSON object which is getting build in filterUserDetails() to 'field' key.

Upvotes: 2

Views: 10940

Answers (2)

georgeos
georgeos

Reputation: 2501

You should be aware that your field can be very complex but in the case you mentioned, can be resolved with this:

resolveField(data: any, field: string): any {
  if (data && field) {
    let fields: string[] = field.split('.');
    let value = data;
    for(let i = 0, len = fields.length; i < len; ++i) {
      if (value == null) {
        return null;
      } else {
        const pos: number = fields[i].match(/\d+/g)?.[0];
        if(pos != null) {
          const property = fields[i].match(/^\w+/g);
          value = value[property][pos];
        } else {
          value = value[fields[i]];
        }
      }
    }
    return value;
  } else {
    return null;
  }
}

You can use the resolveField function as part of your logic. You can modify it, as you want or required, for example: here is considering only letters as part of the property names.

Here is the solution for your code.

Upvotes: 1

ControlAltDel
ControlAltDel

Reputation: 35011

You can use a variable that has the dynamic key

var obj = {
  ...
}
var key = ...;

obj[key] = somevalue;

or to get the value

var somevalue = obj[key];

Upvotes: 2

Related Questions