如何使用angular在打字稿中使用动态键访问JSON对象值

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

我想访问 JSON 对象中存在的值,并为接收到的响应提供可配置的 targetPath。

下面是我的组件 class,它将列表中的数据绑定到 HTML 代码

中的自动完成下拉列表

可配置键是 'path',我想在自定义 JSON 对象键 '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: 'test@gmail.com'
            }
          }
        ]
      },
      {
        id: 'cont-610',
        contactMedium: [
          {
            characteristic: {
              emailAddress: 'test@gmail.com'
            }
          }
        ]
      },
      {
        id: 'cont-611',
        contactMedium: [
          {
            characteristic: {
              emailAddress: 'test@gmail.com'
            }
          }
        ]
      },
      {
        id: 'cont-612',
        contactMedium: [
          {
            characteristic: {
              emailAddress: 'test@gmail.com'
            }
          }
        ]
      },
      {
        id: 'cont-614',
        contactMedium: [
          {
            characteristic: {
              emailAddress: 'test@gmail.com'
            }
          }
        ]
      }
    ];
  }

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

根据从方法 getUserDetails() 收到的响应,我正在构建一个带有字段 'id' 和 'field' 的自定义 JSON 对象数组,id 的键是已知的,它本身是'id' 但字段的键是可配置的,在我的例子中是路径。

但看起来上面访问密钥的逻辑没有按预期工作,即我没有获得

的价值
  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;
  }

下面是我的HTML代码

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

如果我像下面那样更改赋值的用法,一切正常

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

Link 我的代码在这里:https://stackblitz.com/edit/primeng-autocomplete-demo-dyihrs?file=src%2Fapp%2Fapp.component.html

这里的期望是将从 getUserDetails() 接收到的键值:contactMedium[0].characteristic.emailAddress 分配给自定义 JSON 对象,该对象正在 filterUserDetails() 中构建到 'field'键。

您可以使用具有动态键的变量

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

obj[key] = somevalue;

或者获取值

var somevalue = obj[key];

您应该知道您的字段可能非常复杂,但在您提到的情况下,可以通过以下方式解决:

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

您可以将 resolveField 函数用作逻辑的一部分。您可以根据需要或要求修改它,例如:这里只考虑字母作为 属性 名称的一部分。

这是您的代码的solution