Angular响应式表单中,ng-bootstrap typeahead无法工作

3

这是我的组件文件

import {NgbTypeahead} from '@ng-bootstrap/ng-bootstrap';
import { map, switchMap, finalize, debounceTime, distinctUntilChanged, filter } from 'rxjs/operators';
import { Subject, merge } from 'rxjs';

const states = [.....]

// inside class
@ViewChild('instance', {static: true}) instance: NgbTypeahead;
focus$ = new Subject<string>();
click$ = new Subject<string>();

search = (text$: Observable<string>) => {
const debouncedText$ = text$.pipe(debounceTime(200), distinctUntilChanged());
const clicksWithClosedPopup$ = this.click$.pipe(filter(() => !this.instance.isPopupOpen()));
const inputFocus$ = this.focus$;

return merge(debouncedText$, inputFocus$, clicksWithClosedPopup$).pipe(
  map(term => (term === '' ? states
    : states.filter(v => v.toLowerCase().indexOf(term.toLowerCase()) > -1)).slice(0, 10))
);
}

而且在我的html中,我使用了响应式表单绑定

<input
    id="typeahead-focus"
    type="text"
    class="form-control"
    formControlName="userAssigned" 
    [ngbTypeahead]="search"
    (focus)="focus$.next($event.target.value)"
    (click)="click$.next($event.target.value)"
    #instance="ngbTypeahead"
    />

我也在ngOnInit()中初始化了我的表单,就像这样

this.form = this.fb.group({
  userAssigned: ['', Validators.required],
});

当我运行这段代码并点击输入时,我会在弹出窗口中得到结果,但是出现了错误。同时,在清除第一个结果时也无法获得结果。

enter image description here

请帮忙。

你是否将代码包含在<div [formGroup]="form">中?使用的ng-bootstrap版本是多少(我的是"^5.1.1")?这段代码对我来说是有效的,可以查看forked的stackblitz https://stackblitz.com/edit/angular-jclc4z?file=src%2Fapp%2Fapp.component.html - Eliseo
@Eliseo 是的,我有 <div [formGroup]="form">。我使用的版本是(Angular 8.1.2、ng-bootstrap 5.1.1、bootsctrap css 4.3.1)。我按照你的 stackblitz,但找不到我做错了什么。 - Hareesh
@Eliseo 我也发现 (focus) 在代码中没有问题,只有当我 (click) 输入时才会出错。我 fork 了你的 stackblitz 并更改了我正在使用的版本。在那里它可以正常工作,但在我的代码中却不行。我不知道我做错了什么。 - Hareesh
看一下我的回答,只需要在过滤器中添加 this.instance 即可。(我也更新了 Stackblitz) - Eliseo
1个回答

3
问题在于当声明搜索函数时,“instance未定义”。例如,如果我们有以下内容:
<div *ngIf="form" [formGroup]="form">
...
</div>

解决方法是在过滤器中加入this.instance,变成像this.instance && !this.instance.isPopupOpen

因此,完成的搜索函数即为:

    search = (text$: Observable<string>) => {
    const debouncedText$ = text$.pipe(debounceTime(200), distinctUntilChanged());
    const clicksWithClosedPopup$ = this.click$.pipe(filter(() => 
      this.instance && !this.instance.isPopupOpen())); //<---HERE
    const inputFocus$ = this.focus$;

    return merge(debouncedText$, inputFocus$, clicksWithClosedPopup$).pipe(
      map(term => (term === '' ? states
        : states.filter(v => v.toLowerCase().indexOf(term.toLowerCase()) > -1)).slice(0, 10))
    );
  }

谢谢,你是对的。现在它已经通过了所有验证。 - Hareesh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接