專案用到Kendo UI的自動完成,提示資料的物件陣列存在Client端,資料有多個欄位,希望做到任一個欄位包含關鍵字就顯示,AutoComplete有個filter參數,設定為"contains"就可以做到"包含"就算數,但搜尋對象參數dataTextField卻只能指定單一欄位,無法一次查詢多欄。

有個解決辦法是自行在物件上將多個欄位另外併成一欄,例如以下的codePage物件,textForSearch屬性等於代碼加空白加名稱:

      var $code = $("#code");
      function codePage(code, name) {
        this.codePage= code;
        this.name = name;
        this.textForSearch = code + " " + name;
      }
      var data = [
        new codePage("869", "Greek"),
        new codePage("932", "Japanese"),
        new codePage("936", "Simplified Chinese"),
        new codePage("949", "Korea"),
        new codePage("950", "Traditional Chinese")
      ];
      $code.kendoAutoComplete({
        dataTextField: "textForSearch",
        dataValueField: "codePage", 
        dataSource: data,
        filter: "contains",
        select: function (e) {
            //get index of <LI>
            var idx = $.inArray(e.item[0], e.sender.items());
            var data = e.sender.dataItem(idx);
            //set name
            $("#name").text(data.name);
        }
      });

如此,將dataTextField設為textForSearch就能同時搜尋CodePage代碼及名稱:

但有個問題,雖然欄位輸入CodePage代碼或名稱都能搜尋,但我們希望自動完成欄位固定只輸入代碼,名稱則由另一個<SPAN>顯示。當AutoComplete的dataTextField設為textForSearch,點選提示項目後欄位填入的也會是textForSearch的值,會同時有代碼及名稱,與期望不符。

要解決這個問題,有個不錯的方法是透過dataValueField參數指定要填入<INPUT>的屬性名稱。要增加dataValueField功能得修改Kendo UI原始碼,不過修改3rd Party程式庫會增加版控複雜性,追完原始碼,我找到事後置換kendoAutoComplete物件的_select函式的玩法,可不修改原始碼JS就加入新功能,於是用以下的"Patch"函式,傳入data("kendoAutoComplete")取得的物件,將.select換成修改版(其實只改了一行),完成Hacking:

    var SELECTED = "k-state-selected", List = kendo.ui.List;
    function patchKendoAutoComp(autoCompObject) {
        //add optionValueField support to 2013.2.716 version 
        autoCompObject._select = function (li) {
            var that = this,
                separator = that.options.separator,
                data = that._data(),
                text,
                idx;
 
            li = $(li);
 
            if (li[0] && !li.hasClass(SELECTED)) {
            
                idx = List.inArray(li[0], that.ul[0]);
 
                if (idx > -1) {
                    data = data[idx];
                    //if dataValueField provided, use _value
                    text = that.options.dataValueField ? that._value(data) : 
                           that._text(data);
 
                    if (separator) {
                        text = replaceWordAtCaret(caretPosition(that.element[0]), that._accessor(), text, separator);
                    }
 
                    that._accessor(text);
                    that.current(li.addClass(SELECTED));
                }
            }
        }
    }

為AutoComplete增加dataValueField參數有助提高應用彈性,在官方討論區PO了提議,希望未來有機會加入規格,就不需要這個額外Hacking囉!

線上展示


Comments

# by 吳宇

請問黑大, 試用了Kendo UI 一陣子,有個問題想請教,UI總是透過美工設計,但是 Kendo UI 似乎包好好,要調到與美工設計的很接近,都需要花很多時間,不知黑大用在專案中是否有類似的情形?

# by Jeffrey

to 吳宇, 同意,Kendo UI預設的視覺風格,的確與中文網頁一般慣用的樣式有些差異(中文網頁多半字體較小,排列較緊密),要貼近自家美工設計需要耗費一番工夫是事實。依我自己的經驗,Kendo UI採用的CSS套用規則還算模組化,配合IE Dev Tools直接由看到的網頁元素去反推CSS來源,修改後重整就可看結果,調整過程還算直覺流暢,個人覺得痛苦指數在可承受範圍內。 調整樣式是不管用哪一家的UI套件都會面臨的問題,故可把它視為專案中無法逃避的客製工程排入時程。等處理CSS的經驗多了加上熟能生巧,這就不太會是問題了。

# by 吳宇

謝謝黑大

# by benson

AutoComplete确实不会搜多列,所以我做了个dropSearch,可以指定单列或多列搜,像智能手机查联系人时,输数字,按电话号码查,输中文,按联系人姓名或地址等搜查,演示地址: http://jsfiddle.net/bangking/1y1zgaku/

# by Jeffrey

to benson, 感謝分享!

Post a comment