2

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.

2 Answers 2

2

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];
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for the suggestion, but seems we need to manipulate array structure here at run time.
1

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.

Comments

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.