Angular 尝试在使用管道之前等待一个可观察对象发出/初始化
我使用ngbtypeahead作为一个自动完成搜索选项,用户键入一些内容,这个键入的值被发送到父组件,然后父组件调用服务器,返回的值(可观察的)然后被传递回子组件。 我试图做的是,只要我的Angular 尝试在使用管道之前等待一个可观察对象发出/初始化,angular,rxjs,ng-bootstrap,Angular,Rxjs,Ng Bootstrap,我使用ngbtypeahead作为一个自动完成搜索选项,用户键入一些内容,这个键入的值被发送到父组件,然后父组件调用服务器,返回的值(可观察的)然后被传递回子组件。 我试图做的是,只要我的typeAhead组件从父组件(显示为自动完成选项的结果)接收到数据作为@input,就用switchMap(我的管道末端)发出,数据是调用服务器的结果。最初(在键入任何内容之前)数据为空,因此typeAhead组件对数据有一个未定义的值。 我的问题是,我第一次键入似乎发生的情况是,管道在typeAhead(子
typeAhead
组件从父组件(显示为自动完成选项的结果)接收到数据作为@input
,就用switchMap
(我的管道末端)发出,数据是调用服务器的结果。最初(在键入任何内容之前)数据
为空,因此typeAhead
组件对数据
有一个未定义的值。
我的问题是,我第一次键入似乎发生的情况是,管道在typeAhead(子)组件接收到数据之前完成,这导致它显示无自动完成选项。下面是我的代码,我的主要问题是我的handleTypeahead
函数有什么问题,当我在AUTCOMPLE中键入时,它没有发出键入的值
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()
}
}
以及(父级的)模板:
我有点难以理解问题所在。我敢肯定,在您订阅的内容解决之前,subscribe()
是不可能执行的。听起来好像有两个组件在起作用——父组件和子组件——但只有其中一个的共享代码。你能创建一个MVP来演示这个问题吗?@JeffryHouser添加了更多的代码,希望这能澄清问题。这里有太多不相关的代码,所以很难理解。你应该做一个测试。但是你不能用管道(filter(data=>!!data))
过滤掉空值吗?@ritaj我不是想过滤掉null
值,我想让管道等到数据
有一个值。目前,数据是在有值之前发出的,如果我只是过滤,那么它不会发出任何东西。基本上,这一行应该等待数据:switchMap(()=>this.data)
实际上@ritaj comment,是您在具有非空值之前进行可观察的等待的答案。在数据不为空之前,您的流不会继续。对我来说,了解问题是什么有点困难。我敢肯定,在您订阅的内容解决之前,subscribe()
是不可能执行的。听起来好像有两个组件在起作用——父组件和子组件——但只有其中一个的共享代码。你能创建一个MVP来演示这个问题吗?@JeffryHouser添加了更多的代码,希望这能澄清问题。这里有太多不相关的代码,所以很难理解。你应该做一个测试。但是你不能用管道(filter(data=>!!data))
过滤掉空值吗?@ritaj我不是想过滤掉null
值,我想让管道等到数据
有一个值。目前,数据是在有值之前发出的,如果我只是过滤,那么它不会发出任何东西。基本上,这一行应该等待数据:switchMap(()=>this.data)
实际上@ritaj comment,是您在具有非空值之前进行可观察的等待的答案。在数据不为空之前,流不会继续。
<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>
/* 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>