我有一些复选框:

<input type='checkbox' value="apple" checked>
<input type='checkbox' value="orange">
<input type='checkbox' value="pear" checked>
<input type='checkbox' value="naartjie">

我想绑定到我的控制器中的一个列表,这样每当一个复选框被更改时,控制器就会维护一个包含所有选中值的列表,例如,['apple', 'pear']。

Ng-model似乎只能将一个复选框的值绑定到控制器中的一个变量。

是否有其他方法可以将这四个复选框绑定到控制器中的列表?


当前回答

你不需要编写所有的代码。AngularJS会通过使用ngTrueValue和ngFalseValue来使模型和复选框保持同步

代码在这里:http://codepen.io/paulbhartzog/pen/kBhzn

代码片段:

<p ng-repeat="item in list1" class="item" id="{{item.id}}">
  <strong>{{item.id}}</strong> <input name='obj1_data' type="checkbox" ng-model="list1[$index].data" ng-true-value="1" ng-false-value="0"> Click this to change data value below
</p>
<pre>{{list1 | json}}</pre>

其他回答

根据我在这里的另一篇文章,我已经做了一个可重用的指令。

查看GitHub存储库

(function () { angular .module("checkbox-select", []) .directive("checkboxModel", ["$compile", function ($compile) { return { restrict: "A", link: function (scope, ele, attrs) { // Defining updateSelection function on the parent scope if (!scope.$parent.updateSelections) { // Using splice and push methods to make use of // the same "selections" object passed by reference to the // addOrRemove function as using "selections = []" // creates a new object within the scope of the // function which doesn't help in two way binding. scope.$parent.updateSelections = function (selectedItems, item, isMultiple) { var itemIndex = selectedItems.indexOf(item) var isPresent = (itemIndex > -1) if (isMultiple) { if (isPresent) { selectedItems.splice(itemIndex, 1) } else { selectedItems.push(item) } } else { if (isPresent) { selectedItems.splice(0, 1) } else { selectedItems.splice(0, 1, item) } } } } // Adding or removing attributes ele.attr("ng-checked", attrs.checkboxModel + ".indexOf(" + attrs.checkboxValue + ") > -1") var multiple = attrs.multiple ? "true" : "false" ele.attr("ng-click", "updateSelections(" + [attrs.checkboxModel, attrs.checkboxValue, multiple].join(",") + ")") // Removing the checkbox-model attribute, // it will avoid recompiling the element infinitly ele.removeAttr("checkbox-model") ele.removeAttr("checkbox-value") ele.removeAttr("multiple") $compile(ele)(scope) } } }]) // Defining app and controller angular .module("APP", ["checkbox-select"]) .controller("demoCtrl", ["$scope", function ($scope) { var dc = this dc.list = [ "selection1", "selection2", "selection3" ] // Define the selections containers here dc.multipleSelections = [] dc.individualSelections = [] }]) })() label { display: block; } <!DOCTYPE html> <html> <head> <link rel="stylesheet" href="style.css" /> </head> <body ng-app="APP" ng-controller="demoCtrl as dc"> <h1>checkbox-select demo</h1> <h4>Multiple Selections</h4> <label ng-repeat="thing in dc.list"> <input type="checkbox" checkbox-model="dc.multipleSelections" checkbox-value="thing" multiple> {{thing}} </label> <p>dc.multipleSelecitons:- {{dc.multipleSelections}}</p> <h4>Individual Selections</h4> <label ng-repeat="thing in dc.list"> <input type="checkbox" checkbox-model="dc.individualSelections" checkbox-value="thing"> {{thing}} </label> <p>dc.individualSelecitons:- {{dc.individualSelections}}</p> <script data-require="jquery@3.0.0" data-semver="3.0.0" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script> <script data-require="angular.js@1.5.6" data-semver="1.5.6" src="https://code.angularjs.org/1.5.6/angular.min.js"></script> <script src="script.js"></script> </body> </html>

一种简单的HTML方法:

<input type="checkbox" ng-checked="fruits.indexOf('apple') > -1" ng-click="fruits.indexOf('apple') > -1 ? fruits.splice(fruits.indexOf('apple'), 1) : fruits.push('apple')"> <input type="checkbox" ng-checked="fruits.indexOf('orange') > -1" ng-click="fruits.indexOf('orange') > -1 ? fruits.splice(fruits.indexOf('orange'), 1) : fruits.push('orange')"> <input type="checkbox" ng-checked="fruits.indexOf('pear') > -1" ng-click="fruits.indexOf('pear') > -1 ? fruits.splice(fruits.indexOf('pear'), 1) : fruits.push('pear')"> <input type="checkbox" ng-checked="fruits.indexOf('naartjie') > -1" ng-click="fruits.indexOf('apple') > -1 ? fruits.splice(fruits.indexOf('apple'), 1) : fruits.push('naartjie')">

有两种方法可以解决这个问题。要么使用简单数组,要么使用对象数组。每种解决方案都有其优缺点。下面你将为每种情况找到一个解决方案。


使用简单数组作为输入数据

HTML可以是这样的:

<label ng-repeat="fruitName in fruits">
  <input
    type="checkbox"
    name="selectedFruits[]"
    value="{{fruitName}}"
    ng-checked="selection.indexOf(fruitName) > -1"
    ng-click="toggleSelection(fruitName)"
  > {{fruitName}}
</label>

适当的控制器代码是:

app.controller('SimpleArrayCtrl', ['$scope', function SimpleArrayCtrl($scope) {

  // Fruits
  $scope.fruits = ['apple', 'orange', 'pear', 'naartjie'];

  // Selected fruits
  $scope.selection = ['apple', 'pear'];

  // Toggle selection for a given fruit by name
  $scope.toggleSelection = function toggleSelection(fruitName) {
    var idx = $scope.selection.indexOf(fruitName);

    // Is currently selected
    if (idx > -1) {
      $scope.selection.splice(idx, 1);
    }

    // Is newly selected
    else {
      $scope.selection.push(fruitName);
    }
  };
}]);

优点:简单的数据结构和切换名称容易处理

缺点:添加/删除很麻烦,因为必须管理两个列表(输入和选择)


使用对象数组作为输入数据

HTML可以是这样的:

<label ng-repeat="fruit in fruits">
  <!--
    - Use `value="{{fruit.name}}"` to give the input a real value, in case the form gets submitted
      traditionally

    - Use `ng-checked="fruit.selected"` to have the checkbox checked based on some angular expression
      (no two-way-data-binding)

    - Use `ng-model="fruit.selected"` to utilize two-way-data-binding. Note that `.selected`
      is arbitrary. The property name could be anything and will be created on the object if not present.
  -->
  <input
    type="checkbox"
    name="selectedFruits[]"
    value="{{fruit.name}}"
    ng-model="fruit.selected"
  > {{fruit.name}}
</label>

适当的控制器代码是:

app.controller('ObjectArrayCtrl', ['$scope', 'filterFilter', function ObjectArrayCtrl($scope, filterFilter) {

  // Fruits
  $scope.fruits = [
    { name: 'apple',    selected: true },
    { name: 'orange',   selected: false },
    { name: 'pear',     selected: true },
    { name: 'naartjie', selected: false }
  ];

  // Selected fruits
  $scope.selection = [];

  // Helper method to get selected fruits
  $scope.selectedFruits = function selectedFruits() {
    return filterFilter($scope.fruits, { selected: true });
  };

  // Watch fruits for changes
  $scope.$watch('fruits|filter:{selected:true}', function (nv) {
    $scope.selection = nv.map(function (fruit) {
      return fruit.name;
    });
  }, true);
}]);

优点:添加/删除非常容易

缺点:有些复杂的数据结构和切换名称是麻烦的或需要一个帮助方法


演示:http://jsbin.com/ImAqUC/1/

如果在同一个表单上有多个复选框

控制器代码

vm.doYouHaveCheckBox = ['aaa', 'ccc', 'bbb'];
vm.desiredRoutesCheckBox = ['ddd', 'ccc', 'Default'];
vm.doYouHaveCBSelection = [];
vm.desiredRoutesCBSelection = [];

视图代码

<div ng-repeat="doYouHaveOption in vm.doYouHaveCheckBox">
    <div class="action-checkbox">
        <input id="{{doYouHaveOption}}" type="checkbox" value="{{doYouHaveOption}}" ng-checked="vm.doYouHaveCBSelection.indexOf(doYouHaveOption) > -1" ng-click="vm.toggleSelection(doYouHaveOption,vm.doYouHaveCBSelection)" />
        <label for="{{doYouHaveOption}}"></label>
        {{doYouHaveOption}}
    </div>
</div>

<div ng-repeat="desiredRoutesOption in vm.desiredRoutesCheckBox">
     <div class="action-checkbox">
          <input id="{{desiredRoutesOption}}" type="checkbox" value="{{desiredRoutesOption}}" ng-checked="vm.desiredRoutesCBSelection.indexOf(desiredRoutesOption) > -1" ng-click="vm.toggleSelection(desiredRoutesOption,vm.desiredRoutesCBSelection)" />
          <label for="{{desiredRoutesOption}}"></label>
          {{desiredRoutesOption}}
     </div>
</div>        

我在控制器中放了一个数组。

$scope.statuses = [{ name: 'Shutdown - Reassessment Required' },
    { name: 'Under Construction' },
    { name: 'Administrative Cancellation' },
    { name: 'Initial' },
    { name: 'Shutdown - Temporary' },
    { name: 'Decommissioned' },
    { name: 'Active' },
    { name: 'SO Shutdown' }]

在标记上,我添加了如下内容

<div ng-repeat="status in $scope.statuses">
   <input type="checkbox" name="unit_status" ng-model="$scope.checkboxes[status.name]"> {{status.name}}
   <br>                        
</div>
{{$scope.checkboxes}}

输出如下,在控制器中,我只需要检查它是真还是假;选中为True,未选中为null /false。

{
"Administrative Cancellation":true,
"Under Construction":true,
"Shutdown - Reassessment Required":true,
"Decommissioned":true,
"Active":true
}

希望这能有所帮助。