将 API 中的 JSON 数据实现到 mat-autocomplete 输入中

Implement JSON data from API into mat-autocomplete input

我正在尝试将 Angular Material 组件 "Highlight the first autocomplete option" 用于输入,该输入使用来自 API 服务器的 JSON 数据(通过获取所有 JSON数据)。不知道我哪里错了。

我曾尝试使用 Angular Material 示例,但它使用了硬编码方法,我需要来自 API

的数据

service.ts

import { Appl } from '../intdets';
export class IntdetsService {
  private url = "/assets/IntDet.json";
  constructor(private http: HttpClient) { }

  getName(): Observable<Appl[]> {
    return this.http.get<Appl[]>(this.url);
  }
}


intdets.ts

export class Appl {
    _NAME: string;
}

JSON

{
  "_APPLS": [
    {
     "_NAME": "some string",
    },...]}

component.ts

export class IntdetsComponent implements OnInit {
  public apps = [];
  testCtrl: FormControl;
  filteredTest: Observable<Appl[]>;

  constructor(private _intdetsService: IntdetsService) { 
this.testCtrl = new FormControl();
    this.filteredTest = this.testCtrl.valueChanges
      .pipe(
            startWith(null),
            switchMap(val => { return this.filterTest(val || '' )}));
  }
  filterTest(val: string) {
    return this._intdetsService.getName().pipe(
      map(res => res.filter(s => {
        return s._NAME.toLowerCase().indexOf(val.toLowerCase()) === 0
      }))
    ) 
  }
  ngOnInit() {
    this._intdetsService.getName()
        .subscribe(data => {
          this.apps = data;
          console.log(data);
         });
  }
}

HTML
         <mat-form-field >
            <mat-label>Test Name</mat-label>
            <input type="text" matInput [formControl]="testCtrl" [matAutocomplete]="autoTest">
            <mat-autocomplete autoActiveFirstOption #autoTest="matAutocomplete">
               <mat-option *ngFor="let test of filteredTest | async" [value]="test._APPLS">
               {{test._NAME}}
               </mat-option>
            </mat-autocomplete>
         </mat-form-field>
      </p>

你想要的数组在_APPLS里面,所以你需要提取它:

getName(): Observable<Appl[]> {
  return this.http.get<any>(this.url).pipe(
    map(data => data._APPL as Appl[])
  )
}

我还建议,在服务中,您可以在第一次获取后将响应存储在一个变量中。我们不想通过在每次击键时获取数据来使 api 过载。你可以这样做:

data = <Appl[]>[];

getName(): Observable<Appl[]> {
 return this.data.length 
   ? of(this.data) 
   : this.http.get<any>(this.url).pipe(
       map(data => { 
         this.data = data._APPL as Appl[]
         return this.data;
       })
     )
}

您还可以考虑在表单控件更改中添加 debounceTime