角度 ng 选择虚拟滚动功能



我的页面由几个由 *ngFor 指令创建的 ng-select(自定义服务器端搜索(下拉列表组成,可以从每个下拉列表中选择多个项目。

我还想包含虚拟滚动功能,但我不知道如何发出另一个服务器请求并更新filterValues$值以包含新数据。

组件.html

<ng-select [items]="filterValues$[filter.name] | async"
[typeahead]="filterValuesInput$[filter.name]"
[virtualScroll]="true"
[multiple]="true"
[closeOnSelect]="false"
[loading]="filterValuesLoading[filter.name]"
[(ngModel)]="filter.filter_values"
(scrollToEnd)="onScrollToEnd(filter.name)"
(open)="onFilterOpen(filter.name)"
typeToSearchText="No values found"
bindLabel="name">
</ng-select>

组件.ts

onScrollToEnd(filterName) {
this.fetchMore(filterName);
}
fetchMore(filterName) {
this.filterValues$[filterName] = combineLatest(this.getFilterValues(filterName, this.afterKey), of(this.existingValues))
.pipe(
map(combined => {
return combined[1].concat(combined[0])
})
);
}
getFilterValues(filterName, after) {
return this.filterValuesInput$[filterName].pipe(
tap(() => this.filterValuesLoading[filterName] = true),
startWith(''),
distinctUntilChanged(),
switchMap(term  => this.search.getFilterValues(filterName, '' + term, '' + after).pipe(
tap(res => {
this.afterKey = res.after_key;
this.filterValuesLoading[filterName] = false;
this.existingValues = this.existingValues.concat(res.filter_values);
this.totalFilterValues = res.total_hits;
//this.bufferLength += this.initialValues.length;
}),
map(res => res.filter_values),
catchError(() => of([])) // empty list on error
))
)
}

任何帮助将不胜感激!

使用更新的代码进行编辑: 我设法实现了虚拟滚动功能,但每当我转到下拉列表底部时,它都会触发fetchMore()方法并重置this.filterValues$[filterName]值,将下拉列表从下到上移动。我怎样才能防止这种情况发生?

我遇到了同样的问题。

问题是 ng-select 尝试查找所选值的选项,该选项在第一次加载时可能不可用。例如,您正在加载前 15 个值,但所选选项位于稍后的位置,即使您获取更多,它也可能仍然不在下一次提取中。因此,如果您调用 next,它会将您设置为下拉列表的第一个位置。

如果您使用鼠标滚轮滚动,这可能不是问题,因为它会自动聚焦在鼠标光标所在的位置。 但是如果你使用箭头,它总是会跳到开头(这是我的问题(。

我的解决方案是添加一个附加选项(选定的选项(始终在选项列表的开头(因此ng-select可以找到它(+列表的其余部分。 然后,该选项可能会在列表中重复,但是将列表中的第一个选项设置为最初选择的选项是一种用户友好的选择。

请注意,我使用的是 ControlValueAccessor。

protected _itemsBufferSource$ = new BehaviorSubject<unknown[]>([]);    
public items$: Observable<unknown[]> = EMPTY;
public input$ = new Subject<string>();
public virtualScrollItems: unknown[] = [];
public itemsBuffer$: Observable<unknown[]> = this._itemsBufferSource$.asObservable();
<ng-select
#singleSelect
[items]="(enableVirtualScrolling ? this.itemsBuffer$ : this.items$) | async"
...
[(ngModel)]="valueChanged"
...
const firstValue:unknown[] = [this.valueChanged];
...
this._itemsBufferSource$.next(
//add first value to beginning so it would find selected value and arrow virtual scrolling would work(filter out the nulls so there's no error)
firstValue.concat(this.virtualScrollItems.slice(0, this.virtualScrollingBufferSize)).filter(x => x != null));

最新更新