46

Bootstrap2.1.1とjQuery1.8.1を使用していて、Typeaheadの機能を使用しようとしています。

ラベルを表示して、標準のようなIDを使用しようとしています<select />

これが私の先行入力の初期化です:

$(':input.autocomplete').typeahead({
    source: function (query, process) {
        $('#autocompleteForm .query').val(query);
        return $.get(
            $('#autocompleteForm').attr('action')
          , $('#autocompleteForm').serialize()
          , function (data) {
              return process(data);
          }
        );
    }
});

これが私が送信しているJSONの種類です

[{"id":1,"label":"machin"},{"id":2,"label":"truc"}]

process()ラベルを表示し、選択したIDを別の非表示フィールドに保存するように指示するにはどうすればよいですか?

4

10 に答える 10

79

これを行う方法を説明する素晴らしいチュートリアルがここにあります:http://tatiyants.com/how-to-use-json-objects-with-twitter-bootstrap-typeahead/(そうでない場合はそのページの私のコメントを読んでください投稿の主要部分にはまだ反映されています)。

そのチュートリアルと提供したJSONに基づいて、次のようなことができます。

$(':input.autocomplete').typeahead({
    source: function(query, process) {
        objects = [];
        map = {};
        var data = [{"id":1,"label":"machin"},{"id":2,"label":"truc"}] // Or get your JSON dynamically and load it into this variable
        $.each(data, function(i, object) {
            map[object.label] = object;
            objects.push(object.label);
        });
        process(objects);
    },
    updater: function(item) {
        $('hiddenInputElement').val(map[item].id);
        return item;
    }
});                    
于 2012-11-07T22:13:45.773 に答える
14

Twitter Typeaheadのバージョン0.10.1(https://github.com/twitter/typeahead.js)の時点で、Id/Labelはネイティブでサポートされています。

  $('input[name=address]').typeahead({
        hint: false
    }, {
        source: function (query, cb) {
            $.ajax({
                url: '/api/addresses?q=' + encodeURIComponent(query),
                dataType: 'json',
                cache: false,
                type: 'GET',
                success: function (response, textStatus, jqXHR) {
                    cb(response.data);
                },
                error: function (jqXHR, textStatus, errorThrown) {
                }
            });
        },
        name: 'addresses',
        displayKey: 'text'
    }).on('typeahead:selected', function (e, suggestion, name) {
        window.location.href = '/' + suggestion.id;
    });

上記の例の場合、オブジェクトの配列をソースコールバック(cb)に渡します。displayKey:'text'を指定することにより、自動提案に'text'プロパティを使用するようにライブラリに指示しています。'typeahead:select'コールバックが呼び出されると、渡される2番目の引数(提案)には、選択されたオブジェクトが含まれます。

于 2014-02-14T10:00:10.723 に答える
6

コメントで私が言っていたことを明確にするため。同じページで複数のタイプアヘッドが必要な場合は、関数でそれぞれを定義し、それらに対して個別のマップ変数を作成する必要があります。

function initFromField() {
    var map;
    $('#from:input.autocomplete').typeahead({
        source: function(query, process) {
            map = {};
            var data = [{"id":1,"label":"machin"},{"id":2,"label":"truc"}] // Or get your JSON dynamically and load it into this variable
            objects = constructMap(data, map);
            process(objects);
        },
        updater: function(item) {
            $('#hidden-from-input').val(map[item].id);
            return item;
        }
    });
}

function initToField() {
    var map;
    $('#to:input.autocomplete').typeahead({
        source: function(query, process) {
            objects = [];
            map = {};
            var data = [{"id":1,"label":"machin"},{"id":2,"label":"truc"}] // Or get your JSON dynamically and load it into this variable
            objects = constructMap(data, map);
            process(objects);
        },
        updater: function(item) {
            $('#hidden-to-input').val(map[item].id);
            return item;
        }
    });
}

function constructMap(data, map) {
    var objects = [];
    $.each(data, function(i, object) {
        map[object.label] = object;
        objects.push(object.label);
    });
    return objects;
}

$(function initFields() {
    initFromField();
    initToField();
});

2つのフィールド初期化関数内でマップ変数をスコープした方法に注意してください。これは重要です。両方の入力フィールドで同じマップ変数が使用されないようにします。

于 2013-04-21T23:48:36.687 に答える
5

私は自分でこの問題に苦しんでいます。これが私が思いついた解決策です。このタイプのデータについては、次のようになります。

[{'id':an_id, 'name':a_name}]

だった:

$("#memberSearch").typeahead({
            source: function (query, process) {
                var $this = this //get a reference to the typeahead object
                return $.get('/getSwimmerListJSON',function(data){
                    var options = [];
                    $this["map"] = {}; //replace any existing map attr with an empty object
                    $.each(data,function (i,val){
                        options.push(val.name);
                        $this.map[val.name] = val.id; //keep reference from name -> id
                    });
                    return process(options);
                });
            },
            updater: function (item) {
                console.log(this.map[item],item); //access it here

            }

        });
于 2013-06-26T03:34:21.963 に答える
3

選択された答えはちょっとしたハックです。私は同じことを探していました、そしてこのアプローチは美しく働きます:

https://github.com/twbs/bootstrap/pull/3682

2つの配列を保持します。1つは先行入力が示す名前用で、もう1つは名前の抽出元のオブジェクト用です。オプションの1つを選択すると、その名前を使用して、オブジェクトがどこから来たのかを検索します。

于 2012-10-17T17:30:08.790 に答える
3

これらのソリューションのいくつかで私が見た問題はsource、入力ボックスのすべてのキーアップイベントで関数が繰り返し呼び出されることです。つまり、すべてのキーアップイベントでアレイが構築され、ループされます。

これは必要ありません。クロージャを使用すると、データを1回だけ処理し、source関数内からデータへの参照を維持できます。さらに、次のソリューションは、@ Gerbusのソリューションのグローバル名前空間の問題を解決し、ユーザーが何かを選択した後(たとえば、リストからそのアイテムを削除した場合)にデータの配列を操作できるようにします。

  // Setup the auto-complete box of users
  var setupUserAcUi = function(data) {
      var objects = [];
      var map = {};
      $.each(data, function(i, object) {
          map[object.name] = object;
          objects.push(object.name);
      });

      // The declaration of the source and updater functions, and the fact they
      // are referencing variables outside their scope, creates a closure
      $("#splitter-findusers").typeahead({
        source: function(query, process) {
            process(objects);
        },
        updater: function(item) {
            var mapItem = map[item];
            objects.splice( $.inArray(item, objects), 1 ); // Remove from list
            // Perform any other actions
        }
      });
  };

  // `data` can be an array that you define,
  // or you could pass `setupUserAcUi` as the callback to a jQuery.ajax() call
  // (which is actually how I am using it) which returns an array
  setupUserAcUi(data);
于 2013-04-25T08:18:52.073 に答える
3

これがカプセル化されたソリューションです。このソリューションでは、同じページに複数の先行入力を含めることができます。

これは#13279176Gerbus回答の修正版です。

$('.make-me-typeahead').typeahead({
    source: function (query) {
        var self = this;
        self.map = {};
        var items = [];

        var data = [
            {"id": 1, "label": "machin"},
            {"id": 2, "label": "truc"}
        ];

        $.each(data, function (i, item) {
            self.map[item.label] = item;
            items.push(item.label)
        });

        return items;
    },

    updater: function (item) {
        var selectedItem = this.map[item];
        this.$element.data('selected', selectedItem);
        return item;
    }
});

今、あなたが現在選択されているアイテムのキーを取得する必要があるとき、あなたはただする必要があります$('.make-me-typeahead').data('selected')

于 2014-11-02T21:43:58.217 に答える
1

Pierref関数を実装するもう1つの方法。

var separator = "####";
$("'.autocomplete'").typeahead({
    minLength: 3,
    source: function (query, process) {
        var config = {
            type: 'POST',
            url: 'Requests/AJAX.PHP', //Change it
            cache: 'false',
            data: {
                query: query
            },
            dataType: 'json'
        };

        config.beforeSend = function () {
            //TODO : loading gif
        };

        config.error = function (json) {
            if (json.error) {
                alert(json.error);
            }
        };

        config.success = function (json) {
            if (json.error) {
                alert(json.error);
            }
            var data = [];
            for (var i = 0; i < json.data.length; i++) {
                data.push(json.data[i].id + separator + json.data[i].name);
            }

            process(data);
        };

        $.ajax(config);
    },
    highlighter: function (item) {
        var parts = item.split(separator);
        parts.shift();
        return parts.join(separator);
    },
    updater: function (item) {
        var parts = item.split(separator);
        $('.autocomplete').val(parts.shift());
        return parts.join(separador);
    }
});
于 2013-01-24T11:22:03.407 に答える
1

選択した回答は、一意でないラベル(人の名前など)を処理しません。デフォルトの蛍光ペンのフォーマットを維持する次のものを使用しています。

            var callback = function(id) {
                console.log(id);
            };

            $('.typeahead',this.el).typeahead({
                source: function (query, process) {

                    var sourceData = [
                        {id:"abc",label:"Option 1"},
                        {id:"hfv",label:"Option 2"},
                        {id:"jkf",label:"Option 3"},
                        {id:"ds",label:"Option 4"},
                        {id:"dsfd",label:"Option 5"},
                    ];

                    var concatSourceData = _.map(sourceData,function(item){
                        return item.id + "|" + item.label;
                    });

                    process(concatSourceData);
                },

                matcher : function(item) {
                    return this.__proto__.matcher.call(this,item.split("|")[1]);
                },

                highlighter: function(item) {
                    return this.__proto__.highlighter.call(this,item.split("|")[1]);
                },

                updater: function(item) {
                    var itemArray = item.split("|");
                    callback(itemArray[0]);
                    return this.__proto__.updater.call(this,itemArray[1]);
                }
            });
于 2013-11-05T12:15:20.277 に答える
-1

私はAngular2ディレクティブtypeahead-angular2を作成しました。これは、必要なことを正確に実行し、一意でないラベルの場合も処理します。あなたは先行入力の部分を取ることができます。

このディレクティブは、複数の属性を持つ複雑なオブジェクトを処理し、ラベルが一意でない場合を処理します。基本的に4つのパラメータを受け取ります:

  • @Input() name;//先行入力の名前
  • @Input() objectsDataSet;//オブジェクトのデータセット。任意の種類のオブジェクトにすることができます
  • @Input() handleFunction;//オブジェクトが選択されたときに呼び出されるコールバック関数。オブジェクトまたは必要なものをこの関数に渡すことができます。
  • @Input() labelAtt;//ラベル属性(object[labelAtt]ユーザーに表示されます。文字列である必要があります)。

例 :

<input type="text" class="form-control" placeholder="Name..." typeaheadautocomplete [objectsDataSet]="clientList" [labelAtt]="'Firstname'" [name]="'clients'" [handleFunction]="logClient">

ご覧のとおり、: clientListは「クライアント」オブジェクトの配列です{"Fistname":"Billel","Lastname":"Guerfa",....}。オートコンプリートリストにFirstname属性を使用するとします。logClientここでクライアントオブジェクトを受け取り、それを表示します。

依存関係:

index.htmlレベルで先行入力スクリプトを宣言するだけです。

参照:https ://github.com/BillelGuerfa/typeahead-angular2/

于 2016-05-01T19:54:18.503 に答える