Bei der automatischen Vervollständigung der jQuery-Benutzeroberfläche werden keine Ergebnisse festgestellt


89

Bevor Sie mich darauf hinweisen, habe ich das halbe Dutzend Beiträge zu diesem Thema überprüft, aber ich bin immer noch nicht sicher, warum dies nicht funktioniert.

Mein Ziel ist es zu erkennen, wann die automatische Vervollständigung 0 Ergebnisse liefert. Hier ist der Code:

 $.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!'); }

  })
 }
}); 

Die Suche selbst funktioniert einwandfrei. Ich kann problemlos Ergebnisse anzeigen. So wie ich es verstehe, sollte ich in der Lage sein, die Ergebnisse mit dem Autocomplete-Handler ("Ergebnis") abzufangen. In diesem Fall wird es überhaupt nicht ausgelöst. (Selbst eine generische Warnung oder ein console.log, das nicht auf die Anzahl der Ergebnisse verweist, wird nie ausgelöst.) Der Open Event Handler zeigt die richtige Anzahl von Ergebnissen an (wenn Ergebnisse vorliegen), und der Search und Close Event Handler gibt eine Ergebnisgröße an, die immer einen Schritt zurückliegt.

Ich habe das Gefühl, dass mir hier etwas Offensichtliches und Auffälliges fehlt, aber ich sehe es einfach nicht.


Es sieht so aus, als gäbe es keine einfache Möglichkeit, dies mit einem Widget für die automatische Vervollständigung zu erreichen, das von clientseitigen Daten gesteuert wird. Ist die Verwendung einer Remote-Quelle für das Widget eine Option?
Andrew Whitaker

Antworten:


198

jQueryUI 1.9

jQueryUI 1.9 hat das Widget für die automatische Vervollständigung mit dem responseEreignis gesegnet , mit dem wir feststellen können, ob keine Ergebnisse zurückgegeben wurden:

Wird nach Abschluss einer Suche ausgelöst, bevor das Menü angezeigt wird. Nützlich für die lokale Bearbeitung von Vorschlagsdaten, bei denen kein benutzerdefinierter Rückruf von Quelloptionen erforderlich ist. Dieses Ereignis wird immer ausgelöst, wenn eine Suche abgeschlossen ist, auch wenn das Menü nicht angezeigt wird, weil keine Ergebnisse vorliegen oder die automatische Vervollständigung deaktiviert ist.

In diesem Sinne wird das Hacking, das wir in jQueryUI 1.8 durchführen mussten, ersetzt durch:

$(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();
            }
        }
    });
});​

Beispiel: http://jsfiddle.net/andrewwhitaker/x5q6Q/


jQueryUI 1.8

Ich konnte mit der jQueryUI-API keinen einfachen Weg finden, dies zu tun. Sie könnten jedoch die autocomplete._responseFunktion durch Ihre eigene ersetzen und dann die Standardfunktion jQueryUI aufrufen ( aktualisiert, um das prototypeObjekt der automatischen Vervollständigung zu erweitern ) :

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

Binden Sie dann einen Ereignishandler an das autocompletesearchcompleteEreignis (Inhalt ist das Ergebnis der Suche, ein Array):

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

Was hier passiert ist, dass Sie die responseFunktion der automatischen Vervollständigung in einer Variablen ( __response) speichern und dann verwenden apply, um sie erneut aufzurufen. Ich kann mir keine negativen Auswirkungen dieser Methode vorstellen, da Sie die Standardmethode aufrufen. Da wir den Prototyp des Objekts ändern, funktioniert dies für alle Widgets mit automatischer Vervollständigung.

Hier ist ein funktionierendes Beispiel : http://jsfiddle.net/andrewwhitaker/VEhyV/

In meinem Beispiel wird ein lokales Array als Datenquelle verwendet, aber ich denke nicht, dass dies von Bedeutung sein sollte.


Update: Sie können die neue Funktionalität auch in ein eigenes Widget einbinden und die Standardfunktion für die automatische Vervollständigung erweitern:

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

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

Ändern Ihres Anrufs von .autocomplete({...});:

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

Und binden Sie später an das benutzerdefinierte autocompletesearchcompleteEreignis:

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

Ein Beispiel finden Sie hier : http://jsfiddle.net/andrewwhitaker/VBTGJ/


Da diese Frage / Antwort einige Aufmerksamkeit erhalten hat, dachte ich, ich würde diese Antwort mit einer weiteren Möglichkeit aktualisieren, um dies zu erreichen. Diese Methode ist am nützlichsten, wenn Sie nur ein Widget für die automatische Vervollständigung auf der Seite haben. Diese Methode kann auf ein Widget für die automatische Vervollständigung angewendet werden, das eine Remote- oder lokale Quelle verwendet:

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

In diesem Bereich platzieren ifSie Ihre benutzerdefinierte Logik, die ausgeführt werden soll, wenn keine Ergebnisse erkannt werden.

Beispiel: http://jsfiddle.net/qz29K/

Wenn Sie eine entfernte Datenquelle verwenden, sagen Sie Folgendes:

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

Dann müssen Sie Ihren Code ändern, damit Sie den AJAX selbst aufrufen und erkennen können, wann 0 Ergebnisse zurückkommen:

$("#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, eine Idee, wie ich mit jQuery auf die Elemente im Array "content" zugreifen kann ???
Bongs

@ Bongs: Sie sollten in der Lage sein, direkt über den Index darauf zuzugreifencontents[0]
Andrew Whitaker

Tatsächlich wurde das Inhaltsarray mit dem Benutzernamen und seinem Image gefüllt und konnte nicht durch Angabe des Indexwerts darauf zugreifen. Aber die Lösung herausgefunden. Musste gerne erwähnen, Inhalt [i] .user.username ... :) danke für die Antwort und die tolle Lösung ...
Bongs

Die obige Lösung eignet sich auch hervorragend für die automatische Vervollständigung von PrimeFaces (2.2.x), die auf demselben jQuery-Plugin basiert.
Wrschneider

3
In JqueryUI 1.8.19 wurde die Funktion _response in __response umbenannt. ( goo.gl/zAl88 ). Also, $ .ui.autocomplete.prototype._response wird zu $ ​​.ui.autocomplete.prototype .__ Antwort
crazyphoton

6

Jeder scheint die einfache, integrierte Methode zu ignorieren: Verwenden Sie das Ereignis 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")
    }
  }
})

Diese Funktion wurde in jQuery 1.9 als experimentelle Funktion hinzugefügt ( hier beschrieben ). Zum Juli 2017 ist es noch nicht in der API dokumentiert .


2

Wenn Sie eine entfernte Datenquelle verwenden (z. B. eine MySQL-Datenbank, PHP oder was auch immer auf der Serverseite), gibt es einige andere sauberere Möglichkeiten, um mit einer Situation umzugehen, in der keine Daten an den Client zurückgegeben werden müssen (ohne dass dies erforderlich ist) Hacks oder Änderungen des UI-Codes des Kerncodes).

Ich verwende PHP und MySQL als Remote-Datenquelle und JSON, um Informationen zwischen ihnen zu übertragen. In meinem Fall schien es zu jQuery-Ausnahmefehlern zu kommen, wenn die JSON-Anforderung keine Antwort vom Server erhielt. Daher war es für mich einfacher, einfach eine leere JSON-Antwort von der Serverseite zurückzugeben, wenn keine Daten vorhanden sind, und dann den Client zu behandeln Antwort von dort:

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

die($callback . "([])");

Eine andere Möglichkeit wäre, ein Flag in der Antwort vom Server zurückzugeben, um anzuzeigen, dass keine übereinstimmenden Daten vorhanden sind, und Aktionen auf der Clientseite basierend auf dem Vorhandensein (und / oder Wert) des Flags in der Antwort auszuführen. In diesem Fall lautet die Antwort des Servers wie folgt:

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

Basierend auf diesem Flag können dann Aktionen clientseitig ausgeführt werden:

$.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

Legen Sie nach dem Initialisieren Ihres Autocomplete-Elements die Option messages fest, wenn Sie die Standardbereiche für die Nachrichtenanzeige verwenden möchten:

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

HINWEIS : Dies ist eine experimentelle API (nicht dokumentiert). Entwickler der jQuery-Benutzeroberfläche untersuchen derzeit noch eine vollständige Lösung für die Manipulation und Internationalisierung von Zeichenfolgen.


0

Nach stundenlangem Spielen habe ich endlich einen Trick gefunden, der No match foundin jQuery Autocomplete angezeigt werden kann . Schauen Sie sich den obigen Code an und fügen Sie einfach einen hinzu div, in meinem Fall #ulNoMatchund dessen Stil auf displap:none. Überprüfen Sie in der Callback Success-Methode, ob das zurückgegebene Array hat length == 0. Wenn es da ist, hast du deinen Tag gemacht! :) :)

<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

Ich verstehe nicht, warum sourceParameter mit einem benutzerdefinierten Rückruf nicht ausreichen:

$("#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");
         }
         });
        }
     });
  }

Diese Antwort trägt nichts Neues bei. Akzeptierte Antworten haben denselben Code.
Martin

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

Diese Antwort trägt nichts Neues bei. Akzeptierte Antworten haben denselben Code.
Martin
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.