Внедрить данные JSON из API в автозаполнение ввода mat

Я пытаюсь использовать угловой компонент материала "Выделить первый параметр автозаполнения" на входе, который использует данные JSON с сервера API (который уже работает путем извлечения всех данных 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>

1 ответ

Решение

Массив, который вы хотите, находится внутри _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 на вашей форме управления изменениями.

Другие вопросы по тегам