example - jquery ui css
Detectando no hay resultados en la autocompleta de jQuery UI (8)
jQueryUI 1.9
jQueryUI 1.9 ha bendecido el widget de autocompletar con el evento de response
, que podemos aprovechar para detectar si no se devolvieron los resultados:
Se activa después de que se completa una búsqueda, antes de que se muestre el menú. Útil para la manipulación local de datos de sugerencia, donde no se requiere una devolución de llamada de opción de fuente personalizada. Este evento siempre se activa cuando se completa una búsqueda, incluso si el menú no se mostrará porque no hay resultados o la función Autocompletar está desactivada.
Entonces, teniendo esto en cuenta, el pirateo que tuvimos que hacer en jQueryUI 1.8 se reemplazó por:
$(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();
}
}
});
});
Ejemplo: http://jsfiddle.net/andrewwhitaker/x5q6Q/
jQueryUI 1.8
No pude encontrar una forma sencilla de hacerlo con la API de jQueryUI; sin embargo, podría reemplazar la función autocomplete._response
por la suya y luego llamar a la función jQueryUI predeterminada ( actualizada para extender el objeto prototype
de autocompletar) :
var __response = $.ui.autocomplete.prototype._response;
$.ui.autocomplete.prototype._response = function(content) {
__response.apply(this, [content]);
this.element.trigger("autocompletesearchcomplete", [content]);
};
Y luego vincular un controlador de eventos al evento autocompletesearchcomplete
(el contenido es el resultado de la búsqueda, una matriz):
$("input").bind("autocompletesearchcomplete", function(event, contents) {
$("#results").html(contents.length);
});
Lo que está sucediendo aquí es que estás guardando la función de response
de autocompletar a una variable ( __response
) y luego usando apply
para llamarlo de nuevo. No puedo imaginar ningún efecto negativo de este método ya que está llamando al método predeterminado. Ya que estamos modificando el prototipo del objeto, esto funcionará para todos los widgets de autocompletar.
Aquí hay un ejemplo de trabajo : http://jsfiddle.net/andrewwhitaker/VEhyV/
Mi ejemplo utiliza una matriz local como fuente de datos, pero no creo que eso deba importar.
Actualización: también puede ajustar la nueva funcionalidad en su propio widget, extendiendo la funcionalidad predeterminada de autocompletar:
$.widget("ui.customautocomplete", $.extend({}, $.ui.autocomplete.prototype, {
_response: function(contents){
$.ui.autocomplete.prototype._response.apply(this, arguments);
$(this.element).trigger("autocompletesearchcomplete", [contents]);
}
}));
Cambiando su llamada de .autocomplete({...});
a:
$("input").customautocomplete({..});
Y luego vincular al evento personalizado autocompletesearchcomplete
más tarde:
$("input").bind("autocompletesearchcomplete", function(event, contents) {
$("#results").html(contents.length);
});
Vea un ejemplo aquí : http://jsfiddle.net/andrewwhitaker/VBTGJ/
Dado que esta pregunta / respuesta ha recibido algo de atención, pensé que actualizaría esta respuesta con otra forma de lograr esto. Este método es más útil cuando solo tiene un widget de autocompletar en la página. Esta forma de hacerlo se puede aplicar a un widget de autocompletar que utiliza una fuente remota o local:
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);
}
});
Dentro del if
es donde colocaría su lógica personalizada para ejecutar cuando no se detectan resultados.
Ejemplo: http://jsfiddle.net/qz29K/
Si está utilizando una fuente de datos remota, diga algo como esto:
$("#auto").autocomplete({
source: "my_remote_src"
});
Luego tendrá que cambiar su código para que usted mismo haga la llamada AJAX y pueda detectar cuándo regresan los resultados:
$("#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([]);
}
});
}
});
Antes de que me indiques, sí, he revisado la media docena de publicaciones sobre este tema, pero todavía estoy bloqueado sobre por qué esto no funciona.
Mi objetivo es detectar cuándo la autocompleta produce 0 resultados. Aquí está el código:
$.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!''); }
})
}
});
La búsqueda en sí funciona bien, puedo obtener resultados para que aparezcan sin problemas. Según lo entiendo, debería ser capaz de interceptar los resultados con el controlador autocompletar ("resultado"). En este caso, nunca se dispara en absoluto. (Incluso una alerta genérica o console.log que no hace referencia al número de resultados nunca se dispara). El controlador de evento abierto muestra la cantidad correcta de resultados (cuando hay resultados) y los manejadores de búsqueda de búsqueda y cierre informan un tamaño de resultado que siempre está un paso atrás.
Siento que me falta algo obvio y deslumbrante aquí, pero simplemente no lo veo.
Después de horas jugando, finalmente encontré un truco para mostrar No match found
en el autocompletado de jQuery. Mire el código anterior y simplemente agregue un div
, en mi caso #ulNoMatch
y su estilo configurado para displap:none
. En el método de éxito de devolución de llamada, compruebe si la matriz devuelta tiene una length == 0
. Si está allí, ¡ya hiciste tu día! :)
<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>
Después de inicializar su elemento de autocompletar, establezca la opción de mensajes si desea usar los tramos predeterminados para la indicación del mensaje:
$(<yourselector>).autocomplete(''option'', ''messages'', {
noResults: ''myKewlMessage'',
results: function( amount ) {
return amount + ( amount > 1 ? " results were" : " result was" ) + " found.";
}
});
NOTA : Esta es una API experimental (no documentada). Los desarrolladores de jQuery UI aún están investigando una solución completa para la manipulación e internacionalización de cadenas.
No veo por qué el parámetro source
con una devolución de llamada personalizada no es suficiente. Suponiendo que estamos usando un servicio JSON (P), simplemente tenga en cuenta lo siguiente:
La secuencia de comandos del lado del servidor debe producir JSON válido incluso si no se encuentran resultados, y []
es JSON válido.
La documentación para el parámetro source
sugiere que:
Una devolución de llamada de respuesta, que espera un único argumento: los datos para sugerir al usuario. Estos datos deben filtrarse en función del término proporcionado y pueden estar en cualquiera de los formatos descritos anteriormente para datos locales simples. Es importante cuando se proporciona una devolución de llamada de origen personalizada para manejar los errores durante la solicitud. Siempre debe llamar a la devolución de llamada de respuesta incluso si encuentra un error . Esto asegura que el widget siempre tenga el estado correcto.
Teniendo en cuenta los dos puntos anteriores, lo siguiente debería ser suficiente:
$("#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([]);
}
});
}
});
Si está utilizando una fuente de datos remota (como una base de datos MySQL, PHP o lo que sea del lado del servidor) hay otras maneras más limpias de manejar una situación cuando no hay datos que devolver al cliente (sin la necesidad de ningún hacks o cambios en el código UI del código central).
Utilizo PHP y MySQL como mi fuente de datos remota y JSON para pasar información entre ellos. En mi caso, parecía obtener errores de excepción jQuery si la solicitud JSON no recibía algún tipo de respuesta del servidor, por lo que me resultó más fácil simplemente devolver una respuesta JSON vacía desde el lado del servidor cuando no hay datos y luego manejar el cliente respuesta desde allí:
if (preg_match("/^[a-zA-Z0-9_]*$/", $_GET[''callback''])) {//sanitize callback name
$callback = $_GET[''callback''];
} else { die(); }
die($callback . "([])");
Otra forma sería devolver un indicador en la respuesta del servidor para indicar que no hay datos coincidentes y realizar acciones del lado del cliente en función de la presencia (y / o valor) del indicador en la respuesta. En este caso, la respuesta de los servidores sería algo así como:
die($callback . "([{''nodata'':true}])");
Luego, en base a este indicador, las acciones se pueden realizar desde el lado del cliente:
$.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.
}
});
Todo el mundo parece estar ignorando la forma fácil e integrada: use el mensaje: evento 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")
}
}
})
Esta característica se agregó en jQuery 1.9, como una característica experimental (que se describe aquí ). A julio de 2017, aún no está documentado en la API .
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);
}
});
},
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");
}
});
}
});
}