11

jQuery のオートコンプリート ウィジェットを機能させるのに苦労しています。サーバーからのキーと値のペアのリストを使用しています。

次の要件があります。

ユーザーがウィジェットから値を選択した場合、ID をサーバーに渡したいと思います。

ユーザーが値を選択せず​​に生のテキストを入力するか、既に選択されている値を変更した場合、ID フィールドをクリアして生のテキストだけをサーバーに送信する必要があります。

someAjaxFunctionオートコンプリート ウィジェットが期待するオブジェクトの配列を返すと仮定します: {label:label, value:key}.

最初に、オートコンプリート ウィジェットを次のように設定しました。

$(input).autocomplete({
    source: sourceFunction,
    minLength: 1
});

アイテムの 1 つにカーソルを合わせて選択を変更すると、$(input) によって参照されるテキスト ボックス内のテキストが、ラベルではなく、基になるキーに変更されます。これは、ユーザー インタラクションの観点からは非常に望ましくありません。実際、私がこれを調査している理由は、私が構築しているサイトのユーザーが、入力したテキストが乱数に変わっているように見えることに一貫して困惑していたためです。

テキスト ボックスの下に隠しフィールドを追加し、次のように ID をクロークするために select() および focus() イベントを実装しました。

$(input).autocomplete({
    source: sourceFunction,
    minLength: 1
    focus: function(event, ui) {
        $(idField).val(ui.item.value);
        $(this).val(ui.item.label);
        return false;
    },
    select: function(event, ui) {
        $(idField).val(ui.item.value);
        $(this).val(ui.item.label);
        return false;
    },
    minLength: 1
});

これは、ユーザーがオートコンプリート ドロップダウンによって提供されるスクリプトに固執している場合にうまく機能します。ID はクロークされ、サーバーに正しく送信されます。残念ながら、ユーザーがボックスに自由形式のテキストを入力し、その値に基づいて検索したい場合、ID フィールドはリセットされず、以前に選択した ID がサーバーに送信されます。これもかなり紛らわしいです。

jQuery UI Autocomplete のドキュメントには、changeイベントが一覧表示され、引数のitemプロパティが選択された項目に設定されると記載されています。uiキーを押すと非表示の ID フィールドをリセットし、オートコンプリートが変更された場合に ID を再入力できると考えました。残念ながら、 ID をリセットしてはならない一連のキー押下をキャプチャする keypress イベントに加えて、テキスト ボックス内のテキストを管理するために必要なreturn false上記のイベントのステートメントにより、イベントに ui.item が適切に割り当てられません。selectchange

だから今、私は立ち往生しています-ウィジェットがデフォルトでサポートする必要があると思われる機能をサポートするために他に何を試みることができるか本当にわかりません。このプロセスが本来よりもはるかに複雑であるか、本当に明白な何かが欠けています。利用可能なすべてのイベントとすべての例を選択しましたが、手ぶらで出てきました。実際、jQuery UI ページの「カスタム データと表示」の例でさえ、この問題に悩まされています。

これをカバーするためにサーバー側でいくつかのハックを追加できますが、クライアントレベルでこれを実行できることを本当に望んでいます.

また、別のウィジェットに切り替えるよりも、jQuery UI オートコンプリート ウィジェットに固執したいと思います。

4

4 に答える 4

2

私がオートコンプリートを行っている方法は、入力を含むコンテナー div を作成することです。要素を選択すると、コンテナにスパンを含むリンクが追加され、入力ボックスが非表示になります。

リンクとスパンは、X が付いたボタンのように見えるようにスタイル設定されており、DOM からエントリを削除し、隠しフィールドをクリアし、クリック時に入力ボックスを再表示するためのクリック イベント ハンドラーを備えています。したがって、アイテムが選択されたとき:

  <div class="container">
    <a href="#"><span>Selected Item</span></a>
    <input id="myautocomplete" type="text" />
    <input type="hidden" name="myvalue" value="1" />
  </div>

項目が選択されていない場合:

 <div class="container">
    <input id="myautocomplete" name="myautocomplete" type="text" />
    <input id="myvalue" name="myvalue" type="hidden" value="" />
  </div>

この方法では、項目を選択するように強制されるか、自由形式のテキストを入力します。バックエンドでは、キー 'myvalue' を持つリクエスト パラメータが空の場合、キー 'myautocomplete' を持つリクエスト パラメータを調べます。

于 2010-07-27T13:43:31.643 に答える
1

次のフィールドが設定されていると思います。

<div>
    <input type="text" name="visible" class="autocomplete-reference" />
    <input type="hidden" name="hidden" />
</div>

次のjsを初期化する必要があります(jQuery 1.5.2で動作します):

$(document).ready(function() {
    $('.autocomplete-reference').each(function () {
        $(this).keydown(function(e){
            /*
            * this will reset hidden id reference on each visible field manual change
            * we have to bind it on keydown because we want to recognize event of submiting form by enter after autocomplete set
            */
            if (e.keyCode != 13) {
                $(this).siblings('input[type=hidden]').each(function () {
                    $(this).val('');
                });
            }
        });
        $(this).autocomplete({
            minLength: 1,
            /* you can set appending of autocomplete menu into some container to set css contextually
            appendTo: '#someElem',*/
            source: sourceFunction,
            search:function (event, ui) {
                //TODO ...spinner init...
            },
            open:function (event, ui) {
                /* you can grab autocomplete menu widget by this to manipulate some recognizing id, etc..
                 * $(this).autocomplete('widget')
                */
                //TODO ..stop spinner ...
                $(this).keydown(function(e){
                    /* this is important for live reference updates while arrow keys changes  */
                    if (e.keyCode == 37 || e.keyCode == 39) {
                       $($(this).data('autocomplete').menu.active).find('a').trigger('click');
                    }
                });
            },
            focus: function(event, ui) {
                /* here we'll map our data object onto both fields */
                $(this).val(ui.item.label);
                $(this).siblings('input[type=hidden]').each(function () {
                    $(this).val(ui.item.key);
                });
            },
            select: function(event, ui) {
                /* here we'll map our data object onto both fields */
                $(this).val(ui.item.label);
                $(this).siblings('input[type=hidden]').each(function () {
                    $(this).val(ui.item.key);
                });
            },
            close: function(event, ui) {
                //TODO ..stop spinner ...
            }
        });
    });
});

もちろん、正確な:visibleフィールド値を参照に変換できるサーバーサイド検証があると非常に便利です。

于 2012-01-01T13:38:07.240 に答える
0

event.preventDefaultを使用できます

ui.item.label または ui.item.value を介して選択した値を収集し、必要な値を取得して同じテキスト ボックスに設定します。

var idNameCombo = ui.item.label;
            event.preventDefault();
            $("#mID").val(idNameCombo.split(",")[0].trim());
于 2014-12-28T11:27:53.420 に答える