[英]Angular ng-select “No Items Found” error when typing in characters to filter
I have a ng-select component whose drop-down items look like this image above.我有一个 ng-select 组件,其下拉项看起来像上图。
In an attempt to filter the list, I type in characters into the input control and see this: "No Items Found" despite the fact they are in the list.为了过滤列表,我在输入控件中输入字符并看到:“未找到项目”,尽管它们在列表中。
Here's what I've done to try to figure this out...这是我为解决这个问题所做的工作......
Within the component's own code, there is this filter function.在组件自己的代码中,有这个过滤器 function。 I have found based on setting breakpoints, that there is no searchFn (according to code flow) so the defaultSearchFn is used but doesn't seem to work.我发现基于设置断点,没有searchFn(根据代码流),所以使用了defaultSearchFn,但似乎不起作用。
// Code within the component
filter(term) {
if (!term) {
this.resetFilteredItems();
return;
}
this._filteredItems = [];
term = this._ngSelect.searchFn ? term : stripSpecialChars(term).toLocaleLowerCase();
/** @type {?} */
const match = this._ngSelect.searchFn || this._defaultSearchFn;
/** @type {?} */
const hideSelected = this._ngSelect.hideSelected;
//Because there are no groups keys....
for (const key of Array.from(this._groups.keys())) {
/** @type {?} */
const matchedItems = [];
for (const item of this._groups.get(key)) {
if (hideSelected && (item.parent && item.parent.selected || item.selected)) {
continue;
}
/** @type {?} */
const searchItem = this._ngSelect.searchFn ? item.value : item;
//match is never called
if (match(term, searchItem)) {
matchedItems.push(item);
}
}
//code just skips to this point.
if (matchedItems.length > 0) {
const [last] = matchedItems.slice(-1);
if (last.parent) {
/** @type {?} */
const head = this._items.find(x => x === last.parent);
this._filteredItems.push(head);
}
this._filteredItems.push(...matchedItems);
}
}
}
So no items are found because the itemslist.filteredItems is always null.所以找不到项目,因为 itemslist.filteredItems 始终是 null。
<ng-select
#select
(change)="onSelectChanged(select)"
[(items)]="items"
[searchable]="true"
type="text"
>
<ng-template ng-label-tmp let-item="item">
<span class="dropdown">
{{ item.firstName + " " + item.lastName }}
</span>
</ng-template>
<ng-template
ng-option-tmp
let-item="item"
let-search="searchTerm"
let-index="index"
>
<span class="dropdown"
>{{
item.firstName +
" " +
item.lastName +
" " +
item.middleName +
" " +
"(" +
item.id +
")"
}}
</span>
</ng-template>
</ng-select>
Here's the HTML, have I forgot something to make the filtering work when characters are typed in?这是 HTML,我是否忘记了在输入字符时使过滤起作用的东西?
Ok found out more about ng-select internals and a solution for proper dropdown filtering as one types.好的,了解更多关于 ng-select 内部结构和正确下拉过滤作为一种类型的解决方案。
The key to understanding this is this statement in the component's own filter function shown here.理解这一点的关键是这里显示的组件自己的过滤器 function 中的这条语句。
const match = this._ngSelect.searchFn || this._defaultSearchFn;
This statement allows the user to inject a function, if it's not there;此语句允许用户注入 function,如果它不存在; then the default searchFn is used.然后使用默认的 searchFn。
To inject your own SearchFn, put this into the ng-select html.要注入您自己的 SearchFn,请将其放入 ng-select html。 You will want this for specific complex searching.您将需要它用于特定的复杂搜索。
<ng-select
[searchFn]="searchFunction" //inject your own function here.
[items]="filtered"
type="text">
// the itemsList is iterated and this is called for each item
// just like an array map function
searchFunction(term, item) {
// anything returning true makes it into the filtered list
return item.firstName.includes(term);
}
//any matches are pushed into the itemsList.filteredItems list which is read-only to the outside world.
//see this line up above in the filter method of the ng-select?
this._filteredItems.push(...matchedItems);
If you don't have a registered SearchFn method the defaultSearchFn is called.如果您没有注册的 SearchFn 方法,则会调用 defaultSearchFn。 That function looks like this: function 看起来像这样:
_defaultSearchFn(search, opt) {
/** @type {?} */
const label = stripSpecialChars(opt.label).toLocaleLowerCase();
return label.indexOf(search) > -1;
}
That function was failing to find anything in my situation because there was no opt.label. function 在我的情况下找不到任何东西,因为没有 opt.label。 I believe this is a bug because I used the tmp-lbl template.我相信这是一个错误,因为我使用了 tmp-lbl 模板。 In debug mode, the items on entry were all correct but no index was ever found.在调试模式下,条目上的项目都是正确的,但没有找到索引。
Here was the ng-label-tmp template which should have set the opt.label value.这是应该设置 opt.label 值的 ng-label-tmp 模板。
<ng-template ng-label-tmp let-item="item">
<span>{{ item.firstName + " " + item.lastName }}</span>
</ng-template>
[bindLabel] didn't work because it only binds to single fields. [bindLabel] 不起作用,因为它只绑定到单个字段。
If you have no Searchfn registered and nothing is found via the _defaultSearchFn, then one last chance is kicked out to the user, if you have registered an onSearch handler like this.如果您没有注册 Searchfn 并且没有通过 _defaultSearchFn 找到任何内容,那么如果您已经注册了这样的 onSearch 处理程序,那么最后一次机会被踢给了用户。
(search)="onSearchFunction($event, select)"
But you cannot access the itemsList.FilteredItems from here as it's read-only.但是您不能从这里访问 itemsList.FilteredItems,因为它是只读的。 The event sends in the term and items to work on.事件发送术语和要处理的项目。
It is also accessed from code behind like this:它也可以从后面的代码中访问,如下所示:
@ViewChild(NgSelectComponent, { static: false }) select: NgSelectComponent;
this.select.searchEvent.subscribe((result) => {
let term = result.term;
result.items = this.filtered.find((item) =>
item.firstName.includes(term)
);
});
Note that this method requires you to maintain and bind you own filter list.请注意,此方法需要您维护和绑定您自己的过滤器列表。 Yuck...呸...
Best solution is to use your own injected search function.最好的解决方案是使用自己注入的搜索 function。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.