我正在Select2插件上开发包装器,以制作可重用的Blazor组件。我已经使用JSInterop
集成了它在Blazor中的基本用法。现在,我在使用匹配器的自定义函数集成自定义搜索时遇到了一个问题。事实上,一切都很好,但我没有得到结果,因为我必须使用async function
作为匹配器。我必须使用
var result = await dotNetReference.invokeMethodAsync(searchMethodName, params.term, filterItems);
以从CCD_ 3搜索方法获得搜索结果。
该方法是正确命中并正确返回结果。但是,由于Select2中的matcher函数是同步的,而我的自定义函数是异步的,所以它不会在SelectBox
中显示结果,因为解释器不会等待C#
方法返回结果。
我在下面分享我的Select2init
代码,这样任何人都可以帮助我获得解决方案:
$(id).select2({
placeholder: placeholder,
allowClear: isClearAllowed,
minimumResultsForSearch: minSearchResults,
minimumInputLength: minimumInputLength,
maximumInputLength: maximumInputLength,
matcher: async function (params, data) {
if ($.trim(params.term) === '') {
return data;
}
if (typeof data.children !== 'undefined') {
//Grouped Item
var filterItems = [];
data.children.forEach(function (e) {
filterItems.push({ id: e.id, text: e.text, isDisabled: e.disabled, selected: e.selected });
});
var result = await dotNetReference.invokeMethodAsync(searchCallback, params.term, filterItems);
if (result.length) {
var modifiedData = $.extend({}, data, true);
modifiedData.children = data.children.filter(function (x) {
return result.some((r) => r.id === x.id);
});
return modifiedData;
}
}
else if (typeof data.id !== 'undefined' && data.id != "") {
//UnGrouped Item
}
//No Item
return null;
}
});
我是C#
开发人员,对JavaScript
知之甚少,这就是为什么我可能在这里遗漏了一些东西。Blazor还提供了非异步函数来调用C#
方法,但该函数仅在WebAssembly中可用。我正在使这个插件同时适用于Blazor服务器和WebAssembly。
如果有人帮我完成同步函数的异步调用,我将不胜感激。
因此,经过几个小时的尝试,我找到并实现了一个运行良好的解决方案。
首先,我创建了一个自定义的SelectAdapter
,并制作了所需的方法async
。我必须实现一些不同的逻辑才能得到顺序的结果。我更改了Select.prototype.matches
函数,并通过matcher函数调用添加了await
关键字。在Select.prototype.query
函数中,我还更改了为每个选项调用self.matches(params, option)
函数的方式。我从这篇博客文章中得到了帮助,并使用GitHub存储库找到了原始功能。
$.fn.select2.amd.define("CustomSelectAdapter", ["select2/utils", "select2/data/select", "select2/data/minimumInputLength", "select2/data/maximumInputLength"], function (Utils, Select, MinimumInputLength, MaximumInputLength) {
//changed the matches function to async
Select.prototype.matches = async function (params, data) {
var matcher = this.options.get('matcher');
return await matcher(params, data); //added await which will call our defined matcher function asynchronously
};
//changed query function to async
Select.prototype.query = async function (params, callback) {
var data = [];
var self = this;
var $options = this.$element.children();
for (var i in $options) {
if (!$options[i].tagName || ($options[i].tagName.toLowerCase() !== 'option' && $options[i].tagName.toLowerCase() !== 'optgroup')) {
break;
}
var $option = $($options[i]);
var option = self.item($option);
var matches = await self.matches(params, option); //added await to call the asynced matcher function
if (matches !== null) {
data.push(matches);
}
}
callback({
results: data
});
};
var customSelectAdapter = Utils.Decorate(Select, MinimumInputLength);
customSelectAdapter = Utils.Decorate(customSelectAdapter, MaximumInputLength);
return customSelectAdapter;
});
使用上面的代码创建自定义适配器后,我将适配器分配给dataAdapter
属性(根据官方文档(。
$(id).select2({
placeholder: placeholder,
allowClear: isClearAllowed,
minimumResultsForSearch: minSearchResults,
minimumInputLength: minimumInputLength,
maximumInputLength: maximumInputLength,
dataAdapter: $.fn.select2.amd.require("CustomSelectAdapter"), //assinged the custom created adapter
matcher: async function (params, data) {
.....
}
});