Twitter Bootstrap Typeahead – 标识和标签

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

我尝试显示一个标签,并使用标准的<select /> 标识

这是我的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存储在另一个隐藏的字段?

这里有一个很好的教程,解释了如何做到这一点: 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; } }); 

从Twitter Typeahead( twitter/typeahead.html )版本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; }); 

如果上面的例子,我传递一个对象数组到源callback(cb)。 通过指定displayKey:'text',我告诉图书馆使用'text'属性来进行自动build议。 当“typeahead:select”callback被调用时,在(build议)中传递的第二个参数将包含被选中的对象。

澄清我在评论中的意思。 如果你想在同一页面上提前多个types,你需要在函数中定义每个types,并为它们创build一个单独的地图variables。

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

请注意我如何在两个字段初始化函数中定义mapvariables。 这很重要,它确保两个input字段不使用相同的地图variables。

所选的答案是一个黑客的位。 我正在寻找同样的东西,这种方法的作品非常漂亮:

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

它保留两个数组,一个用于提前显示的名称,另一个用于提取名称的对象。 当select其中一个选项时,它使用名称来查找它从哪里来的对象。

我一直在努力解决这个问题,下面是我提出的解决scheme:

 [{'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 } }); 

我在这些解决scheme中看到的问题是source函数在input框的每个键盘事件中被重复调用。 意思是说,数组正在构build,并在每个关键事件上循环。

这不是必须的。 使用闭包,您只能处理一次数据,并在source函数中维护对它的引用。 另外,下面的解决scheme解决了@ Gerbus解决scheme的全局命名空间问题,并且一旦用户select了某些内容(例如,从列表中删除该项目),也允许您使用数据arrays。

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

这是一个封装解决scheme。 这个解决scheme允许您在同一页面上有多个typeahead。

这是#13279176 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; } }); 

现在,当你需要得到当前select的项目的关键,你只需要$('.make-me-typeahead').data('selected')

只是另一种实现Pierreffunction的方式。

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

我做了一个Angular 2指令, typeahead-angular2 ,它完全符合你的要求,并处理非唯一标签的情况。 你可以把打字的部分。

该指令处理具有多个属性的复合对象,并处理标签不唯一的情况。 它基本上接收4个参数:

  • @Input() name; //键入的名字
  • @Input() objectsDataSet; //对象的数据集,它可以是任何types的对象
  • @Input() handleFunction; //select对象时调用的callback函数,可以将对象或任何你想要的东西传递给这个函数。
  • @Input() labelAtt; //标签属性( object[labelAtt]显示给用户,它必须是一个string)。

例如:

 <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级别声明typeahead脚本即可。

  • 键入: https : //twitter.github.io/typeahead.js/

见: https : //github.com/BillelGuerfa/typeahead-angular2/