[英]Twitter Bootstrap Typeahead - Id & Label
我正在使用Bootstrap 2.1.1和jQuery 1.8.1,并尝试使用Typeahead的功能。
我尝试显示标签,并使用类似于标准<select />
的ID
这是我的预输入初始化:
$(':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( https://github.com/twitter/typeahead.js )的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'回调时,传入的第二个参数(建议)包含选定的对象。
为了澄清我在评论中所说的话。 如果要在同一页面上提前输入多个类型,则需要在函数中定义每个类型并为其创建单独的映射变量。
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变量的范围的。 这很重要,它可以确保两个输入字段都不会使用相同的映射变量。
我自己一直在努力解决这个问题,这是我想出的解决方案,用于处理以下类型的数据:
[{'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
}
});
选定的答案有点骇人听闻。 我一直在寻找相同的东西,这种方法效果很好:
https://github.com/twbs/bootstrap/pull/3682
它保留两个数组,一个数组用于键入的名称,另一个数组用于提取名称的对象。 选择其中一个选项时,它将使用名称从对象来自那里查找对象。
我在其中一些解决方案中看到的问题是,在输入框的每个键入事件上都会重复调用source
函数。 这意味着,将在每次键入事件时构建并循环遍历数组。
这不是必需的。 使用闭包,您只能处理一次数据,并在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);
这是一个封装的解决方案。 此解决方案可让您在同一页面上多次输入。
这是#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;
}
});
现在,当您需要获取当前选定项的密钥时,只需执行$('.make-me-typeahead').data('selected')
这是实现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 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;
//一个dataSet对象,它可以是任何类型的对象@Input() handleFunction;
//当选择对象时调用的回调函数,您可以将对象或任何想要的对象传递给此函数。@Input() labelAtt;
//标签属性(向用户显示object[labelAtt]
,它必须是字符串)。例如:
<input type="text" class="form-control" placeholder="Name..." typeaheadautocomplete [objectsDataSet]="clientList" [labelAtt]="'Firstname'" [name]="'clients'" [handleFunction]="logClient">
如您所见:
clientList
是“ client”对象的数组,假设{"Fistname":"Billel","Lastname":"Guerfa",....}
我们将Firstname属性用于自动完成列表。 这里的logClient
接收一个客户端对象并显示它。依存关系:
只需在index.html级别声明typeahead脚本即可。
- typeahead: https : //twitter.github.io/typeahead.js/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.