練習用NG實現KO範例10 - checked繫結

Live Demo

<!DOCTYPE html>
<html ng-app="sampleApp">
<head>
  <meta charset="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>
<body ng-controller="defaultCtrl">
 
    <div>
        連絡方式選擇: 
        <input type="radio" name="contactOption" value="phone" ng-model="model.contOption" />
        電話
        <input type="radio" name="contactOption" value="email" ng-model="model.contOption" />
        Email
    </div>
    <div>
        (與下拉選單連動: 
        <select ng-model="model.contOption">
            <option value="phone">電話</option>
            <option value="email">Email</option>
        </select>)
    </div>
 
    <div>
        單一Checkbox:
        <input type="checkbox" ng-model="model.singleCbx" />
    </div>
 
    <div>
        多Checkbox對應陣列: 
        <input type="checkbox" check-list="model.cbxItems" value="PC" />PC
        <input type="checkbox" check-list="model.cbxItems" value="NB" />NB
        <input type="checkbox" check-list="model.cbxItems" value="Phone" />Phone
    </div>
 
    <fieldset>
        <legend>物件屬性檢視</legend>
        <dl>
            <dt>contOption屬性</dt>
            <dd ng-bind="model.contOption"></dd>
            <dt>singleCbx屬性</dt>
            <dd ng-bind="model.singleCbx"></dd>
            <dt>cbxItems屬性</dt>
            <dd>
                <div>
                    {{ model.cbxItems.join(', ') }}
                </div>
            </dd>
        </dl>
    </fieldset>
 
  <script src="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) {
            var checked = 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);
            } else if (!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"相同的效果。

[NG系列]
http://www.darkthread.net/kolab/labs/default.aspx?m=post&t=angularjs

Comments

Be the first to post a comment

Post a comment