Как создать Observable массива объектов перед изменением значений? - PullRequest
0 голосов
/ 07 мая 2019

Я следую документации Автозаполнение углового материала (v5 Установка отдельных значений управления и отображения), и у меня возникают некоторые проблемы с загрузкой моих данных.

Проблема Iу меня есть то, что FilterOptions в моем коде не заполняется, пока пользователь не начнет печатать.Мне нужно, чтобы список отображался до того, как пользователь начнет печатать.Я считаю, что это потому, что они используют valueChanges, но я не совсем уверен, как заставить этот кусок кода работать для моего случая.Мне нужны эти функции конвейера и карты, но мне нужно, чтобы список загружался до того, как пользователь изменит значение автозаполнения Mat, а не после.

Код взят из ссылки на документацию, которую я более или менее отразил в моемсобственный код:

<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>
filteredOptions: Observable<User[]>;

  ngOnInit() {
    this.filteredOptions = this.myControl.valueChanges
      .pipe(
        startWith<string | User>(''),
        map(value => typeof value === 'string' ? value : value.name),
        map(name => name ? this.filter(name) : this.categoryList.slice())
      );
  }

  filter(name: string): User[] {
    return this.categoryList.filter(option =>
      option.name.toLowerCase().indexOf(name.toLowerCase()) === 0);
  }

  displayFn(user?: User): string | undefined {
    return user ? user.name : undefined;
  }
this.categoryList = Object.entries(data.category).map(([key, value]) => ({ key, value }));

Я подумал, что, вероятно, мне следует использовать какую-то подписку, но я не могу понять синтаксис, чтобы использовать их с pipe и map.

Ответы [ 2 ]

0 голосов
/ 08 мая 2019

Не могу поверить, что все было так просто, но этот ответ помог решить все. Все, что мне нужно было сделать, это переместить мой код за пределы ngOnInit. как показывать опции автозаполнения в фокусе

Мои фильтрованные опции не ожидали получения данных API, поскольку я поместил их в ngOnInit. Как только я переместил его в подписку на мой вызов API, все работало гладко.

0 голосов
/ 08 мая 2019

Я считаю, что все, что вам нужно сделать, это startWith значение формы:

  ngOnInit() {
    this.filteredOptions = this.myControl.valueChanges
      .pipe(
        startWith(this.myControl.value as string), // typing the control's value
        map(name => name ? this.filter(name) : this.categoryList.slice())
      );
  }

Обратите внимание, что использование метода класса внутри оператора является чем-то вроде анти-паттерна.Обычно важно сохранять чистоту при использовании шаблона Observable - особенно с более сложной логикой.

Чтобы исправить это, вы, вероятно, захотите сделать свой categoryList Observable, а свой filter - чистым.функция (выведите его за пределы вашего компонента и задайте ему другой параметр, чтобы вы могли передать categoryList).

function filter(name: string, categoryList: User[]): User[] {
  categoryList.filter(option =>
      option.name.toLowerCase().indexOf(name.toLowerCase()) === 0);
}

Тогда вы можете сделать так:

  ngOnInit() {
    this.filteredOptions = combineLatest(
      this.myControl.valueChanges.pipe(startWith(this.myControl.value as string)),
      this.categoryList
    ).pipe(
      map(([searchTerm, categoryList]) =>
        searchTerm ? filter(searchTerm, categoryList) : [ ...categoryList ])
    );
  }
...