【Bootstrap】 typeahead自動補全


typeahead

這篇文章記錄了我在使用typeahead的一些問題,不是很全,但是基本夠用。

Bootstrap提供typeahead組件來完成自動補全功能。

兩種用法:

直接給標簽添加屬性

<input type="text" data-provide="typeahead">

通過設置autocomplete="off"來關閉瀏覽器自帶的自動補全功能,以防跟我們的產生沖突。  

通過JavaScript

調用$('.typeahead').typeahead()

typeahead()詳解

參考官方README和其他一些博客的資料,可以了解typeahead函數可以接受的一些參數,這些參數可以通過指定標簽屬性來傳遞,也可以直接在JavaScript中給出。對於標簽屬性傳遞參數來說,需要在參數前加上data-,例如data-source="".

下表為官方README文檔中參數表格的翻譯版本:

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 process callback's single argument.

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動態的查詢。

ajax動態查詢

$("#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進行處理。

ajax動態查詢,定制顯示內容

上面的需求很簡單,但是有的時候要考慮更加完善的情況,比方說現在有一個查詢框,是用來查詢學生姓名的,考慮問題:

學生存在重名情況,我們具體想查詢的是學號為001的叫張三的學生,但我們不能輸入001,需求就是輸入張三,而且查詢的時候,一定是根據學號(主鍵)來查詢的,那么我們可以這樣顯示:

但是如何顯示成這種形式,並且我們如何獲取后面的學號呢?

1.首先,ajax所訪問的后台接口就不能只返回name的字符串數組,而應該返回對象。返回一組Student對象,並且以JSON字符串形式返回。這樣前段所接受的內容就是一個JSON對象的集合

2.但是在顯示上是有問題的,它將顯示為:

我們可以發現幾個問題:1.顯示格式為JSON字符串,2.如果Student類含有其它屬性,那么也會顯示出來,除非我們為了這個需求重新設計一個簡單對象。

現在考慮解決這幾個問題:

1.只保留需要顯示/使用的字段

2.顯示格式正確,不要JSON格式

3.只能根據姓名檢索

source

對於第一個問題,我們需要對數據做預處理,即對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

前面了解到,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方法:

updater

/**
         * 在選中數據后的操作,這里的返回值代表了輸入框的值
         *
         * @param obj
         * @return 選中后,最終輸入框里的值
         */
        updater: function (obj) {
            var item = JSON.parse(obj);
            return item.name;
        }

最終輸入框中我們只讓他回填name。

這樣最終的顯示內容就符合了需求,但是當我們提交表單進行查詢的時候,還是沒有id這個值,這里可能需要一個隱藏域來存放id,我們在updater中將隱藏域的value設置為item.id就可以了。

 

 

 

參考資料:

[1].Bootstrap typeahead使用問題記錄及解決方案

[2].bootstrap-3-typeahead


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM