Попытка подождать, пока один наблюдаемый издаст / инициализирует, прежде чем использовать pipe - PullRequest
0 голосов
/ 16 июня 2019

Я использую ngbtypeahead в качестве опции поиска автозаполнения, пользователь что-то вводит, это типизированное значение отправляется родительскому компоненту, который затем вызывает сервер, возвращаемое значение (Observable) затем передается обратно в ребенок. я пытаюсь сделать только с switchMap (конец моей трубы), как только мой typeAhead компонент получает data как @input от родительского компонента (результаты отображаются как опции автозаполнения), data - это результат звонка на сервер. Изначально (до того, как что-либо было введено) data имеет значение NULL, и поэтому компонент typeAhead имеет неопределенное значение для data. Моя проблема в том, что первый первый раз, когда я набираю то, что, кажется, происходит, заключается в том, что pipe завершается раньше, чем data был получен компонентом typeAhead (дочерний), это приводит к тому, что он отображает нет опции автозаполнения. Мой код приведен ниже, основной вопрос, который у меня возникает, заключается в том, что не так с моей функцией handleTypeahead, которая не выдает введенные значения при вводе в автозаполнение.

import {ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnInit, Output} from '@angular/core';
import {Observable, of} from "rxjs";
import {
  debounceTime,
  delayWhen,
  distinctUntilChanged, filter,
  last,
  map,
  mergeMap,
  switchMap,
  tap,
  withLatestFrom,
} from "rxjs/operators";
import {FilterService} from "@carebox/core";
import {ISearchCriteria} from "@carebox/core";
import {NgbTypeaheadSelectItemEvent} from "@ng-bootstrap/ng-bootstrap";

@Component({
  selector: 'core-ui-typeahead-filter',
  changeDetection: ChangeDetectionStrategy.OnPush,
  templateUrl: './typeahead-filter.component.html',
})
export class TypeaheadFilterComponent implements OnInit {
  @Input() id: string;
  @Input() name: string;
  @Input() caption: string;
  @Input() placeholder: string;
  @Input() cssClass: string;
  @Input() cssStyle: string;
  @Input() function: any;

  @Input() data: Observable<string[]>

  model: any;




  @Output() onTypeahead: EventEmitter<any> = new EventEmitter<any>();
  @Output() onSelect: EventEmitter<any> = new EventEmitter<any>();


  constructor() {
  }




  handleTypeahead = (text$: Observable<string>) => {
    this.data.subscribe(
      (data) => {
        if (data) {
          return text$.pipe(
            distinctUntilChanged(),
            debounceTime(200),
            filter(term => term !== ''),
            tap((term) => console.log("handleTypeahead", term)),
            tap((term) => this.onTypeahead.emit(term)),
            /*map((term: string) => [])*/
            /*map((term: string) => term === '' ? [] : this.data)*/
            // withLatestFrom(this.data),
            switchMap(() => this.data)
          );
        }
      }
    )

  }
handleSelectItem(item) {
  this.onSelect.emit(item);
}

ngOnInit() {
  // this.data.subscribe()
}

}

Соответствующий шаблон:

<div class="form-group">
<label class="label-filters" for="{{id}}">
  {{caption}}
</label>

  <input id="{{id}}"
         name="{{name}}"
         type="text"
         placeholder="{{placeholder}}"
         class="{{cssClass}}"
         style="{{cssStyle}}"
         autocomplete="off"
         [(ngModel)]="model"
         [ngbTypeahead]="handleTypeahead"
         (selectItem)="handleSelectItem($event.item)"
  >
</div>

Одно решение, которое я попробовал, - просто добавить оператор delay с задержкой 500 мс, это работает, но не элегантно и имеет некоторые другие проблемы. Должен быть способ явно ожидать поступления значения @input.

Добавление соответствующего кода в родительский компонент, а также в шаблон:

 /* NctId Filter */
  public NctIdTypeahead(term: string) {
    this.model.NctIdList = [];

    if (!(term && term.length > 0)) {
      return;
    }

    this.searchCriteria.nctIdPrefix = term;
    this.searchCriteria.aggregateOn = 'nctid';
    this.filterService.GetNctIdFilterData(this.searchCriteria).pipe(
      last(),
      map((result: any) => {
        return result.nctid;
      })
    ).subscribe(id => this.NctIdList = of(id))

  }

А также шаблон (родительского):

<div class="col-sm-6 col-md-4 col-lg-3">
    <core-ui-typeahead-filter
      id="NctIdFilter"
      caption="NCT ID"
      placeholder="Type to select NCT ID"
      i18n-placeholder="@@T-trials.trial_protocol_id_filter_placeholder"
      [data]="NctIdList"
      [cssClass]="'form-control'"
      (onTypeahead)="NctIdTypeahead($event)"
      (onSelect)="NctIdSelect($event)">
    </core-ui-typeahead-filter>
  </div>
...