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

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

问题描述

我正在使用角度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>'不可分配 键入可观察".类型可观察"不是 可分配为"any []"类型. 类型可观察"中缺少属性包含"

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

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

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

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

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