KO範例12 - 使用自訂繫結整合KendoUI
0 | 14,814 |
雖然knockout.js已經提供很多好用的繫結,例如: value、text、checked、attr、css... 等等,但實務上一定有無法滿足需求的情境。針對這點,KO允許開發者自訂繫結行為,以滿足專案中稀奇古怪的需求。這已屬進階型應用,但深入了解後就會發現此一擴充特性,讓KO更顯威力強大!!
舉一個常見但重要的需求: 到目前為止,我們繫結的輸入欄位都是Select、TextBox、CheckBox等標準HTML元素,但實務上這類瀏覽器標準操作元件常被使用者嫌棄,嫌土嫌無趣,通常得改用jQuery UI、KendoUI之類UI套件才能上得了檯面。範例12便將展示如何用knockout.js整合KendoUI的日期選擇器。
自訂繫結時,基本寫法是在ko.bindingHandlers加上自訂物件,並實做init及update兩個方法:
ko.bindingHandlers.myBinding = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
// 第一次繫結時觸發, 主要用來設定初值、為元素加上外掛、掛載事件... 等
//element指向對象元素
//透過valueAccess()可取得繫結標的
//透過allBindingsAccessor可取到同一data-bind中其他設定
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
// 第一次繫結及之後每次繫結對象值改變時觸發,主要用來更新元素反應資料改變
}
}
以KendoUI的日期選擇器為例,在init階段的要務是透過element參數取得<input type="text">元素,呼叫valueAccessor()取得ko.observable物件,接著以KendoUI的.kendoDataPicker()方法將TextBox升級成日期選擇器,並在日期選擇器change事件中,將修改後的新值寫回ko.observable。為了示範data-bind可一併傳入其他參數(就像下拉選單的options還可以搭配optionsText/optionsValue一樣),範例再多增加一個kendoDateFormat參數,可用以指定日期選擇器的日期格式。
update會發生在ViewModel屬性改變時,所以我們只需取得屬性新值,透過KendoUI提供的方法將其指定給日期選擇器就大功告。
完整程碼如下: 線上展示
<!DOCTYPE html>
<html>
<head>
<title>Lab 12 - 自訂Binding</title>
<script src="../Scripts/jquery-1.7.2.js"></script>
<script src="../Scripts/knockout-2.1.0.debug.js"></script>
<script src="../Scripts/kendo/kendo.web.min.js" type="text/javascript"></script>
<link href="../Content/kendo/kendo.common.min.css" rel="stylesheet" type="text/css" />
<link href="../Content/kendo/kendo.metro.min.css" rel="stylesheet" type="text/css" />
<script>
ko.bindingHandlers.kendoDate = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
// 第一次繫結時觸發, 主要用來設定初值、為元素加上外掛、掛載事件... 等
//element指向對象元素
var $elem = $(element);
//透過valueAccess()可取得繫結標的
var val = valueAccessor();
//透過allBindingsAccessor可取到同一data-bind中其他設定
var allBindParams = allBindingsAccessor();
//轉換成日期選擇器
$elem.kendoDatePicker({
//用unwrapObservable的好處不管observable或一般屬性,均能順利取值
value: ko.utils.unwrapObservable(val),
//取得日期格式, 使用||技巧補上未指定時的預設值
format: allBindParams.kendoDateFormat || "yyyy/MM/dd",
//使用者選取日期後更新屬性
change: function (e) {
var dp = $elem.data("kendoDatePicker");
//將值設定回ViewModel屬性
if (ko.isObservable(val))
val(dp._value);
}
});
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
// 第一次繫結及之後每次繫結對象值改變時觸發,主要用來更新元素反應資料改變
//將ViewModel的屬性值設定到Kendo UI DatePicker上
var kdd = $(element).data("kendoDatePicker");
kdd.value(ko.utils.unwrapObservable(valueAccessor()));
}
}
function MyViewModel() {
var self = this;
self.regDate = ko.observable(new Date(2012, 11, 21));
self.regDateDisp = ko.computed(function () {
return kendo.toString(self.regDate(), "yyyy/MM/dd");
});
self.setToday = function () { self.regDate(new Date()) };
}
$(function () {
ko.applyBindings(new MyViewModel());
});
</script>
</head>
<body>
<input type="button" value="Set Today" data-bind="click: setToday"/>
<br />
<input type="text" data-bind="kendoDate: regDate" />
<input type="text" data-bind="kendoDate: regDate, kendoDateFormat: 'yyyy-MM-dd'" />
</body>
</html>
操作時,由於左右兩個欄位都繫結到同一個ViewModel屬性,改變左邊欄位會一併會更動右邊欄位值,而右邊透過kendoDateFormat參數額外指定yyyy-MM-dd日期格式,故同一日期值在左右兩欄有不同的顯示結果。最上方的Set Today鈕,按下後會將ViewModel屬性設為當天日期,用以驗證ViewModel到元素方向的繫結運作正確。
已經捲起袖子準備為每個KendoUI元件寫一個自訂繫結了嗎? 且慢! 報告大家好消息,網路上已有佛心的開發寫妥Knockout-Kendo.js了,抱著感恩的心情享用吧!
Comments
Be the first to post a comment