Angular 9:一种形式的多个 ngb-typeahead?
Posted
技术标签:
【中文标题】Angular 9:一种形式的多个 ngb-typeahead?【英文标题】:Angular 9: More than one ngb-typeahead in one form? 【发布时间】:2020-08-03 10:51:31 【问题描述】:我在我的 Angular 9 应用程序中使用 NgbTypeahead component from NG-Boostrap 6.0.3。第一个工作正常,但我的表单有很多。
我是否需要为它们中的每一个添加一个单独的 ViewChild 和一个单独的搜索功能?还是我错过了什么?有人可以给我举个例子吗?
作为参考,这里有一个Stackblitz,只有一个。
【问题讨论】:
是的,你需要两个“搜索”和两个 ViewChilds 谢谢。我害怕那个。 好吧,对不起我的快速评论,当然你可以使用独特的搜索功能(不可能是什么)看到我的回答并道歉我的评论 【参考方案1】:好吧,我的评论真的不正确,假设你有 2 个 ngbTypeHead 你需要那个 focus$ 并且 click$ 是一个数组,为此,你可以使用 map,有些像
focus$ = [0,1].map(_=>new Subject<string>());
click$ = [0,1].map(_=>new Subject<string>());
好吧,你也可以做一些类似的(我使用傻瓜数组和地图)但它是一样的:
focus$ = [new Subject<string>(),new Subject<string>()];
我对模型使用了一个数组
model: any[]=[];
并更改作为参数接收的searchFunction:一个索引,一个实例和一个术语(索引是必要的参考主题
searchType(index,instance, text$)
return (text$: Observable<string>) =>
const debouncedText$ = text$.pipe(
debounceTime(200),
distinctUntilChanged()
);
const clicksWithClosedPopup$ = this.click$[index].pipe(
filter(() => !instance.isPopupOpen())
);
const inputFocus$ = this.focus$[index];
return merge(debouncedText$, inputFocus$, clicksWithClosedPopup$).pipe(
map(term =>
(term === ""
? states
: states.filter(
v => v.toLowerCase().indexOf(term.toLowerCase()) > -1
)
).slice(0, 10)
)
);
;
那么,我们唯一需要的就是改变我们的 ngbTypeahead
<input
...
[(ngModel)]="model[index]"
[ngbTypeahead]="searchType(i,instance,$text)"
(focus)="focus$[i].next($any($event).target.value)"
(click)="click$[i].next($any($event).target.value)"
#instance="ngbTypeahead"
>
你可以在stackblitz看到一个例子
更新如果我们需要不同的数据,我们可以改进传递“数据”的函数搜索,所以,如果我们添加一个新的参数来搜索:
searchType(index,instance, data,text$) //<--pass "data"
return (text$: Observable<string>) =>
const debouncedText$ = text$.pipe(
debounceTime(200),
distinctUntilChanged()
);
const clicksWithClosedPopup$ = this.click$[index].pipe(
filter(() => !instance.isPopupOpen())
);
const inputFocus$ = this.focus$[index];
return merge(debouncedText$, inputFocus$, clicksWithClosedPopup$).pipe(
map(term =>
(term === ""
? data //<--here use data
: data.filter( //<--here use data too
v => v.toLowerCase().indexOf(term.toLowerCase()) > -1
)
).slice(0, 10)
)
);
;
我们可以换个叫法写:
[ngbTypeahead]="searchType(i,instance,states,$text)"
另一种选择是,根据“索引”在一个或另一个数组中搜索,所以函数变得像
searchType(index,instance, text$)
const data=index==0?states:this.fruits; //<--the data according the index
return (text$: Observable<string>) =>
const debouncedText$ = text$.pipe(
debounceTime(200),
distinctUntilChanged()
);
const clicksWithClosedPopup$ = this.click$[index].pipe(
filter(() => !instance.isPopupOpen())
);
const inputFocus$ = this.focus$[index];
return merge(debouncedText$, inputFocus$, clicksWithClosedPopup$).pipe(
map(term =>
(term === ""
? data //<--here use data
: data.filter( //<--here use data too
v => v.toLowerCase().indexOf(term.toLowerCase()) > -1
)
).slice(0, 10)
)
);
;
【讨论】:
聪明的解决方案,谢谢。让我难过的部分是菜单的数据源(此处为“状态”)位于搜索功能内。显然,我的每个菜单都有不同的菜单项数组源。我认为最好从 html 实例中传递它:这个菜单是状态,这个菜单是国家等。 您可以将数据作为参数传递给函数搜索。我更新了我的答案和stackblitz,真的这是一个“丑陋的黑客”如何在stackblitz中传递数据,我使用三元运算符,因为只有2个ngbTypeHead。另一个功能是,根据“索引”,是否在数组中搜索以上是关于Angular 9:一种形式的多个 ngb-typeahead?的主要内容,如果未能解决你的问题,请参考以下文章