這篇文章記錄了我在使用typeahead的一些問題,不是很全,可是基本夠用。html
Bootstrap提供typeahead組件來完成自動補全功能。ajax
<input type="text" data-provide="typeahead">
經過設置autocomplete="off"來關閉瀏覽器自帶的自動補全功能,以防跟咱們的產生衝突。 bootstrap
調用$('.typeahead').typeahead()數組
參考官方README和其餘一些博客的資料,能夠了解typeahead函數能夠接受的一些參數,這些參數能夠經過指定標籤屬性來傳遞,也能夠直接在JavaScript中給出。對於標籤屬性傳遞參數來講,須要在參數前加上data-,例如data-source="".瀏覽器
下表爲官方README文檔中參數表格的翻譯版本:app
Name | Type | Default | Description |
source | array, function | [] | 用來查詢的數據源。能夠是數組或字符串,一個帶有name屬性的JSON對象的數組集合,或者一個函數。函數能夠接受兩個參數,query表明輸入框中你的輸入值(即查詢值),process回調函數。The function may be used synchronously by returning the data source directly or asynchronously via the |
items | number | 8 | 下拉選項中出現條目的最大數量。也能夠設置爲「all」 |
minLength | number | 1 | 出發下拉提示的最小長度字符串。能夠設置爲0,即便沒有填寫任何內容,也會出現提示。 |
showHintOnFocus | boolean or "all" | false | 當輸入框得到焦點時馬上顯示提示。若是設置爲true,顯示全部匹配項。若是設置爲「all」,顯示全部提示,並不會按照當前文本過濾。當你須要一個組合框(Combo Box,由文本框和下拉框組成)功能時,能夠考慮這個。 |
scrollHeight | number, function | 0 | Number of pixels the scrollable parent container scrolled down (scrolled out the viewport). |
matcher | function | case insensitive | 該函數用來肯定匹配條目的規則。接受一個參數,item用於測試查詢字符串是否匹配。經過當前查詢字符串this.query。若是相匹配則返回true |
sorter | function | exact match, case sensitive, case insensitive |
該函數用來對結果進行排序。接受一個參數items而且具備typeahead實例的做用域,經過this.query獲得當前查詢。 |
updater | function | returns selected item | 該函數用來返回選中的條目。接受一個item參數而且具備typeahead實例的做用域。 |
highlighter | function | highlights all default matches | 用來高亮自動補全的結果。接受一個item參數而且擁有typeahead實例的做用域。應該返回html |
displayText | function | item.name || item | 用來獲得數據源的條目的文本表示。接受一個item參數而且擁有typeahead實例的做用域。應該返回一個字符串。 |
autoSelect | boolean | true | 容許你決定是否自動選擇第一個建議。關閉它意味着若是沒有選擇任何內容(或Enter或Tab),輸入將不會清空。 |
afterSelect | function | $.noop() | 選擇一個條目後的回調函數。It gets the current active item in parameter if any. |
delay | integer | 0 | 在查找之間添加延遲 |
appendTo | jQuery element | null | 默認狀況下,菜單將會出如今輸入元素的以後。使用這個選項來添加菜單到其餘div。若是你想使用bootstrap的dropup或者dropdown-menu-right classes,就不要使用它 |
fitToElement | boolean | false | 若是你但願菜單的大小與其所連接的輸入的大小相同,置爲true |
addItem | JSON object | false | 在list的最後添加一個條目,例如「New Entry」。這可能被用到,例如當一個條目在數據集中沒有被找到的時候,彈出對話框。 |
使用靜態的內容網上資料不少,直接給source就能夠了,更加廣泛的需求是:經過aJax動態的查詢。async
$("#search-platform").typeahead({
source: function (query, process) {
return $.ajax({
url: '/domain/xxxx',
type: 'post',
data: {name: query},
success: function (result) {
return process(result);
},
});
}
});
這裏咱們只使用了一個source選項,指定一下數據源,經過上表咱們瞭解到source能夠是一個帶有兩個參數的函數,其兩個參數分別爲query和process,query是當前輸入框中所輸入的內容,process是一個回調函數,它用來將咱們獲得的結果轉換爲typeahead組件能夠識別的數據。結合上面一段代碼,咱們返回的內容是經過ajax請求獲得的結果,可是這個結果通過了process進行處理。ide
上面的需求很簡單,可是有的時候要考慮更加完善的狀況,比方說如今有一個查詢框,是用來查詢學生姓名的,考慮問題:函數
學生存在重名狀況,咱們具體想查詢的是學號爲001的叫張三的學生,但咱們不能輸入001,需求就是輸入張三,並且查詢的時候,必定是根據學號(主鍵)來查詢的,那麼咱們能夠這樣顯示:
可是如何顯示成這種形式,而且咱們如何獲取後面的學號呢?
1.首先,ajax所訪問的後臺接口就不能只返回name的字符串數組,而應該返回對象。返回一組Student對象,而且以JSON字符串形式返回。這樣前段所接受的內容就是一個JSON對象的集合
2.可是在顯示上是有問題的,它將顯示爲:
咱們能夠發現幾個問題:1.顯示格式爲JSON字符串,2.若是Student類含有其它屬性,那麼也會顯示出來,除非咱們爲了這個需求從新設計一個簡單對象。
如今考慮解決這幾個問題:
1.只保留須要顯示/使用的字段
2.顯示格式正確,不要JSON格式
3.只能根據姓名檢索
對於第一個問題,咱們須要對數據作預處理,即對ajax獲取的數據作處理:
success: function (result) {
var resultList = result.items.map(function (item) {
var aItem = {id: item.id, name: item.name};
return JSON.stringify(aItem);
});
return process(resultList);
}
result是接口返回的JSON數據,個人數據被一個items對象所包裹,因此是result.items.map。
前面瞭解到,highlighter是用來高亮匹配項的,這個高亮可使用咱們本身想要的風格。方法的原始實現也是高亮匹配內容,可是這裏不適用,咱們但願只顯示name:
/** * 使用指定的方式,高亮(指出)匹配的部分 * * @param obj 數據源中返回的單個實例 * @returns {XML|void|string|*} 數據列表中數據的顯示方式(如匹配內容高亮等) */ highlighter: function (obj) { var item = JSON.parse(obj); var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&'); return item.name.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) { return '<strong>' + match + '</strong>' }); }
這裏反回了html文本,加粗匹配項。這樣顯示出來的內容就是隻有name的狀況。但這還不夠,你會發現當你選中了一個條目,填充到輸入框的內容仍是JSON格式。咱們還須要重寫updater方法:
/** * 在選中數據後的操做,這裏的返回值表明了輸入框的值 * * @param obj * @return 選中後,最終輸入框裏的值 */ updater: function (obj) { var item = JSON.parse(obj); return item.name; }
最終輸入框中咱們只讓他回填name。
這樣最終的顯示內容就符合了需求,可是當咱們提交表單進行查詢的時候,仍是沒有id這個值,這裏可能須要一個隱藏域來存放id,咱們在updater中將隱藏域的value設置爲item.id就能夠了。