检测到jQuery UI自动完成没有结果

在你指出我之前,是的,我已经回顾了这个话题上的6个post,但是我仍然为什么不起作用。

我的目标是检测何时自动完成产生0结果。 代码如下:

$.ajax({ url:'sample_list.foo2', type: 'get', success: function(data, textStatus, XMLHttpRequest) { var suggestions=data.split(","); $("#entitySearch").autocomplete({ source: suggestions, minLength: 3, select: function(e, ui) { entityAdd(ui.item.value); }, open: function(e, ui) { console.log($(".ui-autocomplete li").size()); }, search: function(e,ui) { console.log("search returned: " + $(".ui-autocomplete li").size()); }, close: function(e,ui) { console.log("on close" + $(".ui-autocomplete li").size()); $("#entitySearch").val(""); } }); $("#entitySearch").autocomplete("result", function(event, data) { if (!data) { alert('nothing found!'); } }) } }); 

search本身工作正常,我可以得到的结果出现没有问题。 据我所知,我应该能够拦截与自动完成(“结果”)处理程序的结果。 在这种情况下,它永远不会起火。 (即使是不引用结果数量的通用警报或console.log也不会触发)。 打开的事件处理程序显示正确的结果数(有结果时),search和closures事件处理程序报告的结果大小始终落后一步。

我觉得我失去了一些显而易见的东西,但我只是没有看到它。

jQueryUI 1.9

jQueryUI 1.9已经为response事件祝福了自动完成小部件,我们可以利用它来检测是否没有返回结果:

在search完成后触发,在显示菜单之前。 用于本地处理build议数据,其中不需要自定义源选项callback。 search完成后,始终会触发此事件,即使由于没有结果或“自动完成”function被禁用,菜单也不会显示。

所以,考虑到这一点,我们必须在jQueryUI 1.8中进行的黑客行为被replace为:

 $(function() { $("input").autocomplete({ source: /* */, response: function(event, ui) { // ui.content is the array that's about to be sent to the response callback. if (ui.content.length === 0) { $("#empty-message").text("No results found"); } else { $("#empty-message").empty(); } } }); });​ 

例如: http : //jsfiddle.net/andrewwhitaker/x5q6Q/


jQueryUI 1.8

我找不到一个简单的方法来完成这个jQueryUI API,但是,您可以用自己的代替autocomplete._response函数,然后调用默认的jQueryUI函数( 更新以扩展自动完成的prototype对象)

 var __response = $.ui.autocomplete.prototype._response; $.ui.autocomplete.prototype._response = function(content) { __response.apply(this, [content]); this.element.trigger("autocompletesearchcomplete", [content]); }; 

然后将一个事件处理程序绑定到autocompletesearchcomplete事件(内容是search的结果,一个数组):

 $("input").bind("autocompletesearchcomplete", function(event, contents) { $("#results").html(contents.length); }); 

这里发生的是你将自动完成的response函数保存到一个variables( __response ),然后使用apply再次调用它。 由于您调用了默认方法,我无法想象这种方法会带来什么坏处。 由于我们正在修改对象的原型,所以这将适用于所有自动填充小部件。

这是一个工作的例子 : http : //jsfiddle.net/andrewwhitaker/VEhyV/

我的例子使用本地数组作为数据源,但我不认为这应该重要。


更新:您也可以将新function包装在自己的小部件中,扩展默认的自动完成function:

 $.widget("ui.customautocomplete", $.extend({}, $.ui.autocomplete.prototype, { _response: function(contents){ $.ui.autocomplete.prototype._response.apply(this, arguments); $(this.element).trigger("autocompletesearchcomplete", [contents]); } })); 

.autocomplete({...});更改您的呼叫.autocomplete({...}); 至:

 $("input").customautocomplete({..}); 

然后再绑定到自定义的autocompletesearchcomplete事件:

 $("input").bind("autocompletesearchcomplete", function(event, contents) { $("#results").html(contents.length); }); 

在这里看到一个例子 : http : //jsfiddle.net/andrewwhitaker/VBTGJ/


由于这个问题/答案已经得到了一些关注,我想我会用另一种方式来更新这个答案来完成这个。 当您在页面上只有一个自动填充小部件时,此方法非常有用。 这样做可以应用到使用远程或本地源的自动完成小部件:

 var src = [...]; $("#auto").autocomplete({ source: function (request, response) { var results = $.ui.autocomplete.filter(src, request.term); if (!results.length) { $("#no-results").text("No results found!"); } else { $("#no-results").empty(); } response(results); } }); 

if里面,你会在没有检测到任何结果的情况下放置自定义的逻辑。

例如: http : //jsfiddle.net/qz29K/

如果您使用的是远程数据源,请说出如下所示的内容:

 $("#auto").autocomplete({ source: "my_remote_src" }); 

然后,您需要更改代码,以便自己进行AJAX调用,并可以检测何时返回0结果:

 $("#auto").autocomplete({ source: function (request, response) { $.ajax({ url: "my_remote_src", data: request, success: function (data) { response(data); if (data.length === 0) { // Do logic for empty result. } }, error: function () { response([]); } }); } }); 

如果您正在使用远程数据源(如MySQL数据库, PHP或服务器端的任何其他数据源),则还有其他更简洁的方法来处理无数据返回给客户端的情况(无需任何黑客或核心代码的UI代码更改)。

我使用PHP和MySQL作为我的远程数据源和JSON来传递它们之间的信息。 在我的情况下,我似乎得到jQueryexception错误,如果JSON请求没有得到某种服务器的响应,所以我发现更容易从服务器端返回一个空的JSON响应,当没有数据,然后处理客户端从那里回应:

 if (preg_match("/^[a-zA-Z0-9_]*$/", $_GET['callback'])) {//sanitize callback name $callback = $_GET['callback']; } else { die(); } die($callback . "([])"); 

另一种方法是在服务器响应中返回一个标志,指示没有匹配的数据,并根据响应中标志的存在(和/或值)执行操作客户端。 在这种情况下,服务器响应将是这样的:

 die($callback . "([{'nodata':true}])"); 

然后根据这个标志动作可以执行客户端:

 $.getJSON('response.php?callback=?', request, function (response) { if (typeof response[0].nodata !== 'undefined' && response[0].nodata === true) { alert('No data to display!'); } else { //Do whatever needs to be done in the event that there is actually data to display. } }); 

初始化自动完成元素后,如果要使用默认跨度显示消息,请设置消息选项:

 $(<yourselector>).autocomplete('option', 'messages', { noResults: 'myKewlMessage', results: function( amount ) { return amount + ( amount > 1 ? " results were" : " result was" ) + " found."; } }); 

注意 :这是一个实验性的API(未logging)。 jQuery UI开发人员仍在研究string操作和国际化的完整解决scheme。

每个人似乎都忽略了简单的内置方式:使用消息:noResults事件。

 $('#field_name').autocomplete({ source: $('#field_name').data('autocomplete-source'), messages: { noResults: function(count) { console.log("There were no matches.") }, results: function(count) { console.log("There were " + count + " matches") } } }) 

作为一个实验性function( 在这里描述 ),jQuery 1.9中添加了这个function。 截至2017年7月, 该API尚未logging在案 。

几小时后,我终于find了一个小窍门,显示jQuery自动完成中No match found 。 看看上面的代码,只需添加一个div ,在我的情况下#ulNoMatch和它的风格设置为displap:none 。 在callback成功方法中检查返回的数组是否length == 0 。 如果它在那里,你就去了,你做了你的一天! 🙂

 <pre><div class="ui-widget1" style="width: auto;"> <asp:TextBox ID="txtSearch" class="tb" runat="server" Width="150px"> </asp:TextBox> <ul id="ulNoMatch" class="ui-autocomplete ui-menu ui-widget1 ui-widget1-content ui-corner-all" role="listbox" aria-activedescendant="ui-active-menuitem" style="z-index: 16; display: none; width: 150px;"> <li class="ui-menu-item" role="menuitem"><a class="ui-corner-all" tabindex="-1">No Matches Found</a></li> </ul> </div><pre> <b> <b> Enter code here <script> $(function () { $("input[id$='txtSearch']").autocomplete({ source: function (request, response) { $.ajax({ url: "splah.aspx/GetByName", data: "{ 'strName': '" + request.term.trim() + "' }", dataType: "json", type: "POST", //cacheLength: 1, contentType: "application/json; charset=utf-8", dataFilter: function (data) { return data; }, success: function (data) { var found = $.map(data.d, function (item) { return { value: item.Name, id: item.id } }); if (found.length == 0) { $("#ulNoMatch").show(); } else { $("#ulNoMatch").hide(); } response(found); }, error: function (XMLHttpRequest, textStatus, errorThrown) { alert(textStatus); } }); }, select: function (event, ui) { $("input[id$='txtSearch']").val(ui.item.label); $("input[id$='txtID']").val(ui.item.id); return false; }, minLength: 1 }); }); </script> 

我不明白为什么source定义callback参数是不够的。 假设我们正在使用JSON(P)服务,请记住以下几点:

即使没有find结果,服务器端脚本也必须生成有效的JSON,而[]是有效的JSON。

source参数的文档表明:

响应callback,需要一个参数:向用户build议的数据。 这些数据应该根据所提供的术语进行过滤,并且可以采用上述任何一种简单的本地数据格式。 提供自定义的源callback来处理请求期间的错误是非常重要的。 即使遇到错误,您也必须始终调用回复callback 这确保了小部件始终具有正确的状态。

牢记上述两点,以下就足够了:

 $("#autocomplete").autocomplete({ source: function (request, response) { $.ajax({ url: "http://example.com/service.json", data: { q: this.term }, success: function (data, textStatus, jqXHR) { // data must be an array containing 0 or more items console.log("[SUCCESS] " + data.length + " item(s)"); response(data); }, error: function (jqXHR, textStatus, errorThrown) { // triggered when AJAX failed because of, for example, malformed JSON console.log("[ERROR] n/a item(s)"); response([]); } }); } }); 
 function SearchText() { $(".autosuggest").autocomplete({ source: function (request, response) { $.ajax({ type: "POST", contentType: "application/json; charset=utf-8", url: "Default.aspx/GetAutoCompleteData", data: "{'username':'" + document.getElementById('txtSearch').value + "'}", dataType: "json", success: function (data.d) { if ((data.d).length == 0) { alert("no result found"); } response(data.d); }, error: function (result) { alert("Error"); } }); } }); } 
 The easiest straight forward way to do it. $("#search-box").autocomplete({ minLength: 2, source:function (request, response) { $.ajax({ url: urlPref + "/Api/SearchItems", data: { term: request.term }, success: function (data) { if (data.length == 0) { data.push({ Id: 0, Title: "No results found" }); } response(data); } }); },