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であっても起動しません)。openイベントハンドラーは正しい数の結果を表示し(結果がある場合)、searchおよびcloseイベントハンドラーは常に1ステップ遅れた結果サイズを報告します。

ここには明白で明白な何かが欠けているような気がしますが、それが表示されません。


クライアント側のデータによって駆動されるオートコンプリートウィジェットでこれを実現する簡単な方法はないようです。ウィジェットにリモートソースを使用することはオプションですか?
Andrew Whitaker

回答:


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/


この質問/回答が注目を集めたので、これを達成するためのさらに別の方法でこの回答を更新したいと思いました。このメソッドは、ページにオートコンプリートウィジェットが1つしかない場合に最も役立ちます。この方法は、リモートまたはローカルのソースを使用するオートコンプリートウィジェットに適用できます。

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を使用して「contents」配列の要素にアクセスする方法を教えてください。
Bongs、2011年

1
@Bongs:インデックスで直接アクセスできるはずですcontents[0]
Andrew Whitaker

実際のところ、コンテンツ配列にはユーザー名とその画像が入力されており、インデックス値を指定してもアクセスできませんでした。しかし、解決策を理解しました。contents [i] .user.username ...のように言及しなければなりませんでした... :)返信と素晴らしい解決策に感謝します...
Bongs

上記のソリューションは、同じ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など、サーバー側の何か)を使用している場合は、クライアントに返すデータがない場合の状況に対処するための他のクリーンな方法がいくつかあります(必要なし)。ハッキングまたはコアコードのUIコードの変更)。

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 foundjQueryオートコンプリートに表示するトリックを見つけました。上記のコードを見て、単純にを追加しdiv、私の場合#ulNoMatch、そのスタイルをに設定し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);
                            }
                            });
                        },

この回答は新しいものを提供するものではなく、受け入れられた回答は同じコードを持っています。
マーティン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.