練習用NG實現KO範例10 - checked繫結
<!DOCTYPEhtml>
<htmlng-app="sampleApp">
<head>
<metacharset="utf-8">
<title>Lab 10 - checked繫結</title>
<style>
body, input
{
font-size: 9pt;
}
fieldset
{
margin-top: 10px;
width: 200px;
padding: 5px;
}
dt, dd
{
float: left;
width: 80px;
height: 20px;
}
</style>
</head>
<bodyng-controller="defaultCtrl">
<div>
連絡方式選擇:
<inputtype="radio"name="contactOption"value="phone"ng-model="model.contOption"/>
電話
<inputtype="radio"name="contactOption"value="email"ng-model="model.contOption"/>
</div>
<div>
(與下拉選單連動:
<selectng-model="model.contOption">
<optionvalue="phone">電話</option>
<optionvalue="email">Email</option>
</select>)
</div>
<div>
單一Checkbox:
<inputtype="checkbox"ng-model="model.singleCbx"/>
</div>
<div>
多Checkbox對應陣列:
<inputtype="checkbox"check-list="model.cbxItems"value="PC"/>PC
<inputtype="checkbox"check-list="model.cbxItems"value="NB"/>NB
<inputtype="checkbox"check-list="model.cbxItems"value="Phone"/>Phone
</div>
<fieldset>
<legend>物件屬性檢視</legend>
<dl>
<dt>contOption屬性</dt>
<ddng-bind="model.contOption"></dd>
<dt>singleCbx屬性</dt>
<ddng-bind="model.singleCbx"></dd>
<dt>cbxItems屬性</dt>
<dd>
<div>
{{ model.cbxItems.join(', ') }}
</div>
</dd>
</dl>
</fieldset>
<scriptsrc="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.js"></script>
<script>
angular.module("sampleApp", [])
//REF: http://stackoverflow.com/a/14519881
.directive('checkList', function() {
return {
scope: {
list: '=checkList',
value: '@'
},
link: function(scope, elem, attrs) {
var handler = function(setup) {
varchecked = elem.prop('checked');
var index = scope.list.indexOf(scope.value);
if (checked&& index == -1) {
if (setup) elem.prop('checked', false);
else scope.list.push(scope.value);
} elseif (!checked&& index != -1) {
if (setup) elem.prop('checked', true);
else scope.list.splice(index, 1);
}
};
var setupHandler = handler.bind(null, true);
var changeHandler = handler.bind(null, false);
elem.on('change', function() {
scope.$apply(changeHandler);
});
scope.$watch('list', setupHandler, true);
}
};
})
.controller("defaultCtrl", function($scope) {
function myViewModel() {
var self = this;
//Radio對應到Value值
self.contOption = "phone";
//單一Checkbox對應到true/false
self.singleCbx = true;
//多個Checkbox對應到Value值組成的字串陣列
self.cbxItems = ["PC", "NB"];
}
$scope.model = new myViewModel();
});
</script>
</body>
</html>
在NG中,可用<input type="checkbox" ng-model="prop">繫結checked屬性到prop上,prop預設為Boolean,但可用ng-true-value/ng-false-value以指定值取代true/false[參考]。對於RadioButton,<input type="radio" value="theValue" ng-model="prop">會將prop繫結到已選取項目的Value值。
至於Checkbox多重選取,KO比NG方便,只要用data-bind="checked: 某個observableArray"就可以得到勾選項目Value所組成的字串陣列。NG未內建Chebkbox多重選取支援,同樣效果需靠自訂Directive。在此借用網友寫的範例,在sampleApp新增名為"checkList"的Directive,跟先前介紹的簡易Directive不同,checkList除了Link函式外,又多宣告了scope: { list: "=checkList", value="@" },為checkList建立Local Scope,其中包含兩個屬性list及value,其中list設為"=checkList",雙向繫結到上層Scope的checkList屬性(亦即HTML標籤check-list="…"所設定的屬性,本例為CheckList選取結果組成的字串陣列);而value="@"代表Local Scope的value來自HTML標籤value="..."所指定的值。(還有一個&符號用來指向可執行的表示式,例如: localFunc: "&action",HTML寫成func="doSomething(arg)",呼叫localFunc({ boo:"Foo" })等同執行doSomething({ boo:"Foo" })。(詳細說明請參考官方文件)
而Link函式以$watch()監測list集合,負責將集合異動反應至Checkbox;同時也透過jQuery change事件監控Checkbox狀態變化,將選取結果更新到list,達成勾選方格與list間的雙向繫結。
最後,將Checkbox寫成<input type="checkbox" check-list="model.cbxItems" value="PC" />,就能實現KO data-bind="checked: cbxItems"相同的效果。