angular 5 material 2 - 自动完成从外部 api 获取数据 [英] angular 5 material 2 - auto complete getting data from external api

查看:17
本文介绍了angular 5 material 2 - 自动完成从外部 api 获取数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是 angular 5 和材料 2.

I'm using angular 5 and material 2.

在 ts 文件中,我有这个属性:

In ts file, I have this proeperty:

      filteredOptions: Observable<any[]>;

此属性将有一组值显示在自动完成字段中.

This property is going to have an array of values to show in the autocomplete field.

      [{
        id:'1', name: 'teste 1'},
        {id:'2', name: 'teste 2'},
        {id:'3', name: 'teste 3'
      }]

这个值数组来自数据库,它将在用户输入内容后显示.

This array of values come from the database and it is going to be shown after the user type something.

html 文件:

          ##            <form class="example-form">
          ##              <mat-form-field class="example-full-width">
          ##                <input type="text" placeholder="Assignee" aria-label="Assignee" matInput [formControl]="myControl" [matAutocomplete]="auto">
          ##                <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
          ##                  <mat-option *ngFor="let option of filteredOptions | async" [value]="option">
          ##                    {{ option.name }}
          ##                  </mat-option>
          ##                </mat-autocomplete>
          ##              </mat-form-field>
          ##            </form>

ts 文件示例:

    this.filteredOptions = Observable<any[]>;

    ngOnInit() {
      this.filteredOptions = this.myControl.valueChanges
        .pipe(
          startWith({}),
          map(getArrayOfValue(val))            
        );
      }

      // it is going to call an api to get the array of values to be shown in the field
      getArrayOfValue(val): Observable<any[]> {            
        const url = this.ROOT_URL + 'veiculo/' + val;
        return this.http.get<any[]>(url);
      }

这段代码给我一个错误

src/app/oficina/cadastro/veiculo/veiculo.component.ts(55,5) 中的错误:错误 TS2322:类型Observable>"不可分配输入可观察的".'Observable' 类型不是可分配到类型 'any[]'.'Observable' 类型中缺少属性 'includes'

ERROR in src/app/oficina/cadastro/veiculo/veiculo.component.ts(55,5): error TS2322: Type 'Observable>' is not assignable to type 'Observable'. Type 'Observable' is not assignable to type 'any[]'. Property 'includes' is missing in type 'Observable'

推荐答案

我看到一些问题,例如你应该map(val => this.getArrayOfValue(val)).但我也建议一些额外的改变.考虑添加 debounceTimedistinctUntilChangedswitchMap.设置您选择的去抖动时间.这不是为了让 api 完全过载.以及 switchMap 可用于使请求切换到用户输入的最后一个值.此外,您应该考虑为您的 api 请求使用服务,这通常是我们处理事情的方式.所以我建议将 http 请求移动到服务并从组件调用它.

I see some issues, for example you should map(val => this.getArrayOfValue(val)). But I would also suggest some additional changes. Think about adding debounceTime, distinctUntilChanged and switchMap. Set a debounce time of your choosing. This, not to completely overload the api. As well as switchMap is useful to make the request switches to the last value user has typed. Also you should consider using a service for your api requests, that is usually how we handle things. So I suggest moving the http-request to the service and call that from the component.

TS:

  // inject your created service which makes the http-request
  constructor(private service: Service) { 

  this.filteredOptions = this.myControl.valueChanges
        .pipe(
          startWith(''),
          debounceTime(400),
          distinctUntilChanged(),
          switchMap(val => {
            return this.filter(val || '')
          })       
        );
  }

  // filter and return the values
 filter(val: string): Observable<any[]> {
    // call the service which makes the http-request
    return this.service.getData()
     .pipe(
       map(response => response.filter(option => { 
         return option.name.toLowerCase().indexOf(val.toLowerCase()) === 0
       }))
     )
   }  
}

Service 然后会调用 http 请求.如果您不重载 API,我们可以在第一次获取后将数据存储在一个变量中,而是返回该变量的 observable,但这只是可选的.

Service would then call the http-request. If you do not overload the API, we could store the data in a variable after first fetch, and instead return an observable of that variable, but that is just optional.

opts = [];

getData() {
  return this.opts.length ?
    of(this.opts) :
    this.http.get<any>('https://jsonplaceholder.typicode.com/users').pipe(tap(data => this.opts = data))
}

您似乎还使用 value 作为模板中的选项.如果要捕获整个对象,请使用 [value].

Also you seem to use value for your option in template. If you want to capture the whole object, use [value].

这是一个演示 供你玩 :)

Here's a DEMO for you to play around with :)

这篇关于angular 5 material 2 - 自动完成从外部 api 获取数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆