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/