Javascript Twitter引导程序Typeahead-Id&;标签

Javascript Twitter引导程序Typeahead-Id&;标签,javascript,jquery,twitter-bootstrap,autocomplete,typeahead.js,Javascript,Jquery,Twitter Bootstrap,Autocomplete,Typeahead.js,我正在使用Bootstrap 2.1.1和jQuery 1.8.1,并尝试使用Typeahead的功能 我尝试显示一个标签,并使用一个id,就像标准的 以下是我的typeahead初始化: $(':input.autocomplete').typeahead({ source: function (query, process) { $('#autocompleteForm .query').val(query); return $.get(

我正在使用Bootstrap 2.1.1和jQuery 1.8.1,并尝试使用Typeahead的功能

我尝试显示一个标签,并使用一个id,就像标准的

以下是我的typeahead初始化:

$(':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存储在另一个隐藏字段中?

所选答案有点老套。我也在寻找同样的东西,这种方法非常有效:


它保留两个数组,一个用于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;
    }
});                    

这是实现Pierref函数的另一种方法

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);
    }
});
var separator=“#####”;
$(“.autocomplete”)。提前键入({
最小长度:3,
来源:功能(查询、流程){
变量配置={
键入:“POST”,
url:'Requests/AJAX.PHP',//更改它
缓存:“false”,
数据:{
查询:查询
},
数据类型:“json”
};
config.beforeSend=函数(){
//TODO:正在加载gif
};
config.error=函数(json){
if(json.error){
警报(json.error);
}
};
config.success=函数(json){
if(json.error){
警报(json.error);
}
var数据=[];
for(var i=0;i
以澄清我在评论中所说的内容。如果希望在同一页上有多个类型ahead,则需要在函数中定义每个类型ahead,并为它们创建单独的map变量

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

注意我是如何在两个字段初始化函数中确定map变量的范围的。这一点很重要,它确保两个输入字段不使用相同的map变量。

我看到的一些解决方案的问题是,在输入框的每个keyup事件上重复调用
source
函数。也就是说,数组正在构建中,并在每个keyup事件上循环

这是没有必要的。使用闭包,您只能处理数据一次,并在
source
函数中维护对数据的引用。此外,下面的解决方案解决了@Gerbus解决方案的全局名称空间问题,还允许您在用户选择某个内容(例如,从列表中删除该项)后使用数据数组


我自己也一直在努力解决这个问题,下面是我提出的解决方案,用于以下类型的数据:

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


所选答案不处理非唯一标签(例如姓名)。我使用的是以下格式,保留默认的高亮格式:

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

从Twitter Typeahead()的0.10.1版开始,本机支持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”回调时,传入的第二个参数(建议)包含所选的对象。

这里是一个封装的解决方案。此解决方案允许您在同一页上有多个typeahead

这是Gerbus答案的修改版本

$('.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')

我生成了一个Angular 2指令,typeahead-angular2,它完全满足您的要求,并处理非唯一标签的情况。你可以选打字前的部分

此指令处理具有多个属性和 处理标签不唯一的情况。它基本上收到了4封信 参数:

  • @Input()名称//typeahead的名称
  • @Input()对象数据集//对象的数据集,可以是任何类型的对象
  • @Input()handleFunction//选择对象时调用的回调函数,可以传递对象或任何需要的内容
    这项职能
  • @Input()labelat
    //标签属性(
    object[labelat]
    显示给用户,它必须是字符串)
例如:

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

正如您所看到的:
clientList
是一个“客户机”对象数组,让我们 说
{“Fistname”:“Billel”,“Lastname”:“Guerfa”,…}
我们使用 自动完成列表的Firstname属性<代码>日志客户端
此处接收 客户端对象并显示它

依赖项: 只需在index.html级别声明typeahead脚本

  • 提前打印:

请参阅:

是否执行任何帮助?需要注意的一点是
map
变量及其范围。根据您的代码,它与
对象
变量一起是全局的。这意味着您一次只能在页面上有一个typeahead,否则地图对象将在typeahead框之间共享
$('.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;
    }
});
<input type="text" class="form-control" placeholder="Name..." typeaheadautocomplete [objectsDataSet]="clientList" [labelAtt]="'Firstname'" [name]="'clients'" [handleFunction]="logClient">