在jQuery UI自动完成功能上未检测到任何结果


89

是的,在您向我指出这些问题之前,我已经审查了有关该主题的六篇文章,但是我仍然对为什么这行不通感到困惑。

我的目标是检测自动填充何时产生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!'); }

  })
 }
}); 

搜索本身工作正常,我可以毫无问题地显示结果。据我了解,我应该能够使用autocomplete(“ result”)处理程序拦截结果。在这种情况下,它根本不会触发。(即使不引用结果数量的通用警报或console.log也不会触发)。打开事件处理程序显示正确的结果数(有结果时),搜索和关闭事件处理程序报告的结果大小始终落后一步。

我觉得我在这里遗漏了一些明显的东西,但我只是看不到它。


似乎没有一种简单的方法可以通过由客户端数据驱动的自动完成小部件来完成此任务。是否为小部件使用远程源是一种选择?
安德鲁·惠特克

Answers:


199

jQueryUI 1.9

jQueryUI 1.9为自动完成小部件添加了response事件,我们可以利用该事件来检测是否未返回任何结果:

搜索完成后触发,然后显示菜单。对于本地处理建议数据很有用,因为不需要自定义源选项回调。即使没有显示菜单,因为没有结果或自动完成功能被禁用,该事件总是在搜索完成时触发。

因此,考虑到这一点,我们在jQueryUI 1.8中不得不做的黑客被替换为:

$(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事件(内容是搜索的结果,一个数组):

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

这是在将自动完成response功能保存到变量(__response),然后apply用于再次调用它。我无法想象此方法会产生任何不良影响,因为您正在调用默认方法。由于我们正在修改对象的原型,因此这将适用于所有自动完成的小部件。

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

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


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

$.widget("ui.customautocomplete", $.extend({}, $.ui.autocomplete.prototype, {

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

将通话从更改.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([]);
            }
        });
    }
});

@Andrew,有什么主意我可以使用jQuery访问“目录”数组中的元素吗???
2011年

1
@Bongs:你应该能够直接索引来访问它contents[0]
安德鲁·惠特克

实际上,问题是内容数组中填充了用户名及其图像,并且无法通过指定索引值来访问它。但是想出了解决方案。不得不提,contents [i] .user.username ... :)感谢您的答复和
出色的

对于基于同一jQuery插件的PrimeFaces自动完成(2.2.x),上述解决方案也非常有用。
wrschneider 2011年

3
在JqueryUI 1.8.19中,_response函数重命名为__response。(goo.gl/zAl88)。因此,$。ui.autocomplete.prototype._response变为$ .ui.autocomplete.prototype .__ response
crazyphoton

6

每个人似乎都忽略了简单的内置方法:使用messages: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")
    }
  }
})

此功能作为实验性功能(在此处介绍)添加在jQuery 1.9中。截至2017年7月,该API尚未记录


2

如果您使用的是远程数据源(例如MySQL数据库,PHP或服务器端的任何数据),则可以使用其他两种更清洁的方法来处理无数据返回客户端的情况(无需任何操作)骇客或核心程式码使用者介面程式码变更)。

我使用PHP和MySQL作为远程数据源,并使用JSON在它们之间传递信息。就我而言,如果JSON请求没有从服务器获得某种响应,我似乎会收到jQuery异常错误,因此我发现在没有数据时从服务器端返回一个空的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.
    }
});

2

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

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

注意:这是实验性的API(未记录)。jQuery UI开发人员仍在研究用于字符串操作和国际化的完整解决方案。


0

在玩了几个小时之后,我终于找到了No match found在jQuery自动完成中显示的技巧。看上面的代码div,在我的情况下#ulNoMatch,简单地添加a ,并将其样式设置为displap:none。在成功的回调方法中,检查返回的数组是否具有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>

0

我不明白为什么source带有自定义回调的参数不够:

$("#autocomplete").autocomplete({
    source: function (request, response) {
        $.ajax({
            url: "http://example.com/service.json",
            data: {
                q: this.term
            },
            success: function (data, textStatus, jqXHR) {
                // data would be an array containing 0 or more items
                console.log("[SUCCESS] search returned " + data.length + " item(s)");
                response(data);
            },
            error: function (jqXHR, textStatus, errorThrown) {
                // triggered when AJAX failed because of, for example, malformed JSON
                console.log("[FAILURE] search returned error");
                response([]);
            }
        });
    }
});

-1
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");
         }
         });
        }
     });
  }

该答案没有贡献任何新内容,接受的答案具有相同的代码。
马丁

-1
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);
                            }
                            });
                        },

该答案没有贡献任何新内容,接受的答案具有相同的代码。
马丁
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.