在使用管道之前尝试等待一个可观察的对象发出/初始化

时间:2019-06-16 10:55:53

标签: angular rxjs ng-bootstrap

我正在使用ngbtypeahead作为自动完成搜索选项,用户键入了一些内容,该键入的值被发送到父组件,该父组件随后对服务器进行调用,然后将返回的值(一个Observable)向下传递给这个孩子。  我想做的是仅在我的switchMap组件从父组件收到typeAhead作为data的情况下,才发出@input(管道的末端)显示为自动完成选项),data是服务器调用的结果。最初(在键入任何内容之前)data为空,因此typeAhead组件的data值未定义。 我的问题是,我第一次键入 似乎是在pipe在typeAhead(子)组件收到data之前完成,结果导致它显示自动完成选项。我的代码在下面,我主要遇到的问题是我的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>

我尝试过的一种解决方案是简单地添加具有500ms延迟的delay运算符,但这可行,但并不美观,并且存在其他一些问题。应该有一种方法可以明确地等待@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>

0 个答案:

没有答案