Angular HttpClient-访问隐藏在响应数据中的值

问题描述

我正在访问在线API,并希望使用文本值来填充ngb-typeahead下拉列表。使用Wikipedia的角度引导网站上有一个working example,但是从Wikipedia API返回的数据与我从地理编码API获得的数据不同。我获取的数据以以下格式返回:

{
 "suggestions": [
  {
   "text": "23 Queen Charlotte Drive,Aotea,Porirua,Wellington,5024,NZL","magicKey": "dHA9MCNsb2M9NDMwNzcyNzQjbG5nPTMzI2huPTIzI2xicz0xMDk6NDg1NDQwMzU=","isCollection": false
  },{
   "text": "23 Queen Mary Avenue,Epsom,Auckland,1023,"magicKey": "dHA9MCNsb2M9NDMwNDY4MjUjbG5nPTMzI2ZhPTE0NDE3OTIjaG49MjMjbGJzPTEwOTo0ODU0NDMyNA==",

我一直尝试通过以下方式访问text作为响应数据:

return this.http
  .get<any>(GIS_URL,{params: GIS_ParaMS.set('text',term)}).pipe(
    map(response => response.suggestions)
  );

我还阅读了有关处理响应数据的Angular教程here,但示例中的不同之处在于它们获取的是Hero数组,而我获取的是包含建议数组的对象。

键入的内容如下:

enter image description here

HTML

<fieldset class="form-inline">
  <div class="form-group">
    <label for="typeahead-http">Search for a wiki page:</label>
    <input id="typeahead-http" type="text" class="form-control mx-sm-3" [class.is-invalid]="searchFailed" [(ngModel)]="model" [ngbTypeahead]="search" placeholder="Wikipedia search" />
    <small *ngIf="searching" class="form-text text-muted">searching...</small>
    <div class="invalid-Feedback" *ngIf="searchFailed">Sorry,suggestions Could not be loaded.</div>
  </div>
</fieldset>
<hr>
<pre>Model: {{ model | json }}</pre>

堆栈代码here中的完整代码

我是新来的,所以详细的答案会很棒。

解决方法

您需要在预输入resultFormatter(请参考https://ng-bootstrap.github.io/#/components/typeahead/api)上指定inputFormatterinput

说明

您在服务中的search方法返回一个建议对象列表,每个对象看起来像:

{
  isCollection: ...
  magicKey: ...
  text: ...
}

但是默认情况下,typeahead控件需要一个字符串列表,因此它会将您的对象显示为[Object object]。

您需要告诉typeahead控件如何从对象中确定字符串值,您可以通过resultFormatterinputFormatter进行操作。

这些输入采用一个函数,该函数以对象作为输入,并以字符串显示值作为输出。

下面的

formatter是该函数,将为列表中显示的每个项目调用该函数。如果将其扩展为普通函数,则可以在其中放置一个断点,并查看以这种方式调用它。

解决方案

<input id="typeahead-http" ... [inputFormatter]="formatter" [resultFormatter]="formatter"/>

TS文件:

formatter = (item:any) => item.text as string;

更新了Stackblitz

https://stackblitz.com/edit/so-typeahead?file=src%2Fapp%2Ftypeahead-http.ts

后续问题

  1. item在格式化程序中:

考虑:

formatter = (item:any) => item.text as string;

的简写:

function format(item: any){ 
  return item.text as string; 
}

他们提前键入控件/指令,以迭代search(..)返回的项目,并分别调用此方法。结果显示在选择列表中。

  1. map(response => response.suggestions)

服务的响应是一个对象,例如:

{  // object
  suggestions:
    [
      { ...,text: 'Place 1' },{ ...,text: 'Place 2' }
    ]
}

这是一个包含名为suggestions的列表的对象。提前输入仅需要一个列表,因此map转换仅包含list => list的对象。

  1. 您定义的格式化程序同时输入和结果吗?

是的,因为它已同时分配给模板中的[inputFormatter][resultFormatter]

,

替代答案

映射完全在服务中完成:

return this.http
      .get<any>(GIS_URL,{params: GIS_PARAMS.set('text',term)}).pipe(
        map(response => response.suggestions.map(suggestion => suggestion.text)),);

每个响应对象都映射到建议列表。
每个建议都使用JS映射映射到其文本值。

如果您不需要访问服务之外的任何其他建议属性,则可以使用此解决方案。