對於Kendo UI AutoComplete的Client端應用,過去的印象還停留在「提供字串陣列作為資料來源」、「指定contains、startswith、endswith進行比對」、「提示項目跟帶入欄位值都來自字串陣列」、「不能限定比對吻合項目上限」,感覺不如jQuery自動完成彈性。如以下範例:Live Demo
若要做到更特殊的比對邏輯或想限制提示筆數,倒是可用serverFiltering實現,將輸入關鍵字以AJAX方式交給伺服器端程式比對再傳回提示項目結果。但對SPA及打算包成App的情境,仰賴伺服器才能運作的自動完成有點掉漆。
最近為了專案的特殊需求,較深入了解KendoAutoComplete後,驚奇發現Kendo UI的架構比想像來得彈性,許多原以為辦不到的規格要求,並不難實現。
以下是KendoAutoComplete小露身手的花式操槍表演,展示重點包含:
- 股票資料以JavaScript陣列方式提供,完全在Client執行,不需伺服器端程式
技巧:使用dataSource,可傳入物件陣列,不限定字串陣列,再以dataTextField指定取用屬性 - 提示區塊可指定不同寬度
技巧:.data("kendoAutoComplete").list.width(…)可指定提示區寬度 - 關鍵字搜尋範圍涵蓋股票代號、中文名稱及英文名稱三個欄位
技巧:dataSource.transport.read()可以自訂JavaScript函式進行比對,取代AJAX呼叫 - 提示項目呈現時,符合關鍵字的欄位(可能是代號、中文或英文三欄之一)靠左顯示,代號及中文名稱靠右顯示,關鍵字部分以紅字標示
技巧:template參數可指定函式,接入資料物件,傳回動態組裝的HTML,完全掌控提示區顯示格式 - 選定提示項目時,只將股票代號填入欄位,中文名稱填入另外欄位,顯示於股票代號之後
技巧:dataTextFiled參數指定要填入,在change事件可取得股票代號值變化,加入自訂邏輯連動其他欄位
程式碼如下:Live Demo
<!DOCTYPEhtml> <htmlng-app="app"> <head> <metacharset="utf-8"> <title>kendoAutoComplete範例:強化版</title> <linkhref="//cdn.kendostatic.com/2014.2.716/styles/kendo.common.min.css"rel="stylesheet"/> <linkhref="//cdn.kendostatic.com/2014.2.716/styles/kendo.default.min.css"rel="stylesheet"/> <style> .hi { color: red; } .hint { clear: both; } .f-l { float: left; } .f-r { float: right; } .symbol { width: 100px; } </style> </head> <bodyng-controller="ctrl as vm"> <div> <inputclass="symbol"kendo-auto-complete="vm.KendoObject" k-options="vm.Options"ng-model="vm.Symbol"/> <spanng-bind="vm.Name"></span> </div> <scriptsrc="//code.jquery.com/jquery-2.1.1.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script> <script src="//cdn.kendostatic.com/2014.2.716/js/kendo.all.min.js"></script> <script> var rawData = [ { s: '1435', c: '中福', e: 'C.F.C.Y.CORP.' }, { s: '1437', c: '勤益', e: 'GTM' }, { s: '1471', c: '首利', e: 'SL' }, //...省略... { s: '8078', c: '華寶', e: 'CCI' }, { s: '8101', c: '華冠', e: 'Arima Comm.' }, { s: '8105', c: '凌巨', e: 'GiantPlus' }, { s: '8249', c: '菱光', e: 'CSI' }, { s: '9912', c: '偉聯', e: 'AIC' } ]; var book = {}; $.each(rawData, function(i, item) { book[item.s] = item; }); function myCtrl($scope) { var self = this; self.Symbol = ""; self.Name = ""; function hiliteKeywd(str, keywd) { return str.replace(keywd, "<span class='hi'>" + keywd + "</span>") } self.Options = { dataTextField: 's', filter: "contains", template: function (item) { return"<div class='hint'><span class='f-l'>" + item.match + "</span><span class='f-r'>" + item.s + " " + item.c + "</span></div>"; }, open: function() { //設定指示區寬度 self.KendoObject.list.width(250); }, change: function() { var symbol = this.value(); if (!symbol) self.Name = ""; else //股票代號連動名稱 self.Name = book[symbol] ? book[symbol].c : ""; }, dataSource: { serverFiltering: true, transport: { read: function (e) { //密技:dataSource.transport可用JavaScript取代Server呼叫 var keywd = e.data.filter.filters[0].value; //輸入數字時比對s、否則比對c或n var isNum = !isNaN(keywd); //設定比對筆數上限 var count = 0, maxCount = 10; //共用比對函式 function check(item, prop) { if (item[prop].indexOf(keywd) > -1) { count++; item.match = item[prop].replace(keywd, "<span class='hi'>" + keywd + "</span>"); returntrue; } returnfalse; } var res = isNum ? $.grep(rawData, function (item) { if (count < maxCount && check(item, "s")) returntrue; else returnfalse; }) : $.grep(rawData, function (item) { if (count < maxCount && check(item, "c") || check(item, "e")) returntrue; else returnfalse; }); //將比對結果傳回 e.success(res); } } } }; } angular.module("app", ["kendo.directives"]) .controller("ctrl", myCtrl); </script> </body> </html> |
補充:Kendo UI有兩個版本,Core版及Profession版。Core版免費並採Apache v2 Open Source授權;Profession版多了Grid、Charts、Editor、TreeView、Upload、Charts等元件,為付費商業元件。AutoComplete包含在Core版。
[NG系列]
http://www.darkthread.net/kolab/labs/default.aspx?m=post&t=angularjs