How do I bind to list of checkbox values with AngularJS?

前端 未结 29 2311
天涯浪人
天涯浪人 2020-11-22 05:20

I have a few checkboxes:





        
相关标签:
29条回答
  • 2020-11-22 06:09

    Here is yet another solution. The upside of my solution:

    • It does not need any additional watches (which may have an impact on performance)
    • It does not require any code in the controller keeping it clean
    • The code is still somewhat short
    • It is requires very little code to reuse in multiple places because it is just a directive

    Here is the directive:

    function ensureArray(o) {
        var lAngular = angular;
        if (lAngular.isArray(o) || o === null || lAngular.isUndefined(o)) {
            return o;
        }
        return [o];
    }
    
    function checkboxArraySetDirective() {
        return {
            restrict: 'A',
            require: 'ngModel',
            link: function(scope, element, attrs, ngModel) {
                var name = attrs.checkboxArraySet;
    
                ngModel.$formatters.push(function(value) {
                    return (ensureArray(value) || []).indexOf(name) >= 0;
                });
    
                ngModel.$parsers.push(function(value) {
                    var modelValue = ensureArray(ngModel.$modelValue) || [],
                        oldPos = modelValue.indexOf(name),
                        wasSet = oldPos >= 0;
                    if (value) {
                        if (!wasSet) {
                            modelValue = angular.copy(modelValue);
                            modelValue.push(name);
                        }
                    } else if (wasSet) {
                        modelValue = angular.copy(modelValue);
                        modelValue.splice(oldPos, 1);
                    }
                    return modelValue;
                });
            }
        }
    }
    

    At the end then just use it like this:

    <input ng-repeat="fruit in ['apple', 'banana', '...']" type="checkbox" ng-model="fruits" checkbox-array-set="{{fruit}}" />
    

    And that is all there is. The only addition is the checkbox-array-set attribute.

    0 讨论(0)
  • 2020-11-22 06:09

    I think the following way is more clear and useful for nested ng-repeats. Check it out on Plunker.

    Quote from this thread:

    <html ng-app="plunker">
        <head>
            <title>Test</title>
            <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.4/angular.min.js"></script>
        </head>
    
        <body ng-controller="MainCtrl">
            <div ng-repeat="tab in mytabs">
    
                <h1>{{tab.name}}</h1>
                <div ng-repeat="val in tab.values">
                    <input type="checkbox" ng-change="checkValues()" ng-model="val.checked"/>
                </div>
            </div>
    
            <br>
            <pre> {{selected}} </pre>
    
                <script>
                    var app = angular.module('plunker', []);
    
                    app.controller('MainCtrl', function ($scope,$filter) {
                        $scope.mytabs = [
                 {
                     name: "tab1",
                     values: [
                         { value: "value1",checked:false },
                         { value: "value2", checked: false },
                         { value: "value3", checked: false },
                         { value: "value4", checked: false }
                     ]
                 },
                 {
                     name: "tab2",
                     values: [
                         { value: "value1", checked: false },
                         { value: "value2", checked: false },
                         { value: "value3", checked: false },
                         { value: "value4", checked: false }
                     ]
                 }
                        ]
                        $scope.selected = []
                        $scope.checkValues = function () {
                            angular.forEach($scope.mytabs, function (value, index) {
                             var selectedItems = $filter('filter')(value.values, { checked: true });
                             angular.forEach(selectedItems, function (value, index) {
                                 $scope.selected.push(value);
                             });
    
                            });
                        console.log($scope.selected);
                        };
                    });
            </script>
        </body>
    </html>
    
    0 讨论(0)
  • 2020-11-22 06:10

    Here's a quick little reusable directive that seems to do what you're looking to do. I've simply called it checkList. It updates the array when the checkboxes change, and updates the checkboxes when the array changes.

    app.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.bind('change', function() {
            scope.$apply(changeHandler);
          });
          scope.$watch('list', setupHandler, true);
        }
      };
    });
    

    Here's a controller and a view that shows how you might go about using it.

    <div ng-app="myApp" ng-controller='MainController'>
      <span ng-repeat="fruit in fruits">
        <input type='checkbox' value="{{fruit}}" check-list='checked_fruits'> {{fruit}}<br />
      </span>
    
      <div>The following fruits are checked: {{checked_fruits | json}}</div>
    
      <div>Add fruit to the array manually:
        <button ng-repeat="fruit in fruits" ng-click='addFruit(fruit)'>{{fruit}}</button>
      </div>
    </div>
    
    app.controller('MainController', function($scope) {
      $scope.fruits = ['apple', 'orange', 'pear', 'naartjie'];
      $scope.checked_fruits = ['apple', 'pear'];
      $scope.addFruit = function(fruit) {
        if ($scope.checked_fruits.indexOf(fruit) != -1) return;
        $scope.checked_fruits.push(fruit);
      };
    });
    

    (The buttons demonstrate that changing the array will also update the checkboxes.)

    Finally, here is an example of the directive in action on Plunker: http://plnkr.co/edit/3YNLsyoG4PIBW6Kj7dRK?p=preview

    0 讨论(0)
  • 2020-11-22 06:10

    Using this example of the @Umur Kontacı, I think in using to catch selected data throughout another object/array, like a edit page.

    Catch options at the database

    Toggle a some option

    As example, all colors json in below:

    {
        "colors": [
            {
                "id": 1,
                "title": "Preto - #000000"
            },
            {
                "id": 2,
                "title": "Azul - #005AB1"
            },
            {
                "id": 3,
                "title": "Azul Marinho - #001A66"
            },
            {
                "id": 4,
                "title": "Amarelo - #FFF100"
            },
            {
                "id": 5,
                "title": "Vermelho - #E92717"
            },
            {
                "id": 6,
                "title": "Verde - #008D2F"
            },
            {
                "id": 7,
                "title": "Cinza - #8A8A8A"
            },
            {
                "id": 8,
                "title": "Prata - #C8C9CF"
            },
            {
                "id": 9,
                "title": "Rosa - #EF586B"
            },
            {
                "id": 10,
                "title": "Nude - #E4CAA6"
            },
            {
                "id": 11,
                "title": "Laranja - #F68700"
            },
            {
                "id": 12,
                "title": "Branco - #FFFFFF"
            },
            {
                "id": 13,
                "title": "Marrom - #764715"
            },
            {
                "id": 14,
                "title": "Dourado - #D9A300"
            },
            {
                "id": 15,
                "title": "Bordo - #57001B"
            },
            {
                "id": 16,
                "title": "Roxo - #3A0858"
            },
            {
                "id": 18,
                "title": "Estampado "
            },
            {
                "id": 17,
                "title": "Bege - #E5CC9D"
            }
        ]
    }
    

    And 2 types of data object, array with one object and object containing two/more object data:

    • Two items selected catched at the database:

      [{"id":12,"title":"Branco - #FFFFFF"},{"id":16,"title":"Roxo - #3A0858"}]
      
    • One item selected catched at the database:

      {"id":12,"title":"Branco - #FFFFFF"}
      

    And here, my javascript code:

    /**
     * Add this code after catch data of database.
     */
    
    vm.checkedColors = [];
    var _colorObj = vm.formData.color_ids;
    var _color_ids = [];
    
    if (angular.isObject(_colorObj)) {
        // vm.checkedColors.push(_colorObj);
        _color_ids.push(_colorObj);
    } else if (angular.isArray(_colorObj)) {
        angular.forEach(_colorObj, function (value, key) {
            // vm.checkedColors.push(key + ':' + value);
            _color_ids.push(key + ':' + value);
        });
    }
    
    angular.forEach(vm.productColors, function (object) {
        angular.forEach(_color_ids, function (color) {
            if (color.id === object.id) {
                vm.checkedColors.push(object);
            }
        });
    });
    
    /**
     * Add this code in your js function initialized in this HTML page
     */
    vm.toggleColor = function (color) {
        console.log('toggleColor is: ', color);
    
        if (vm.checkedColors.indexOf(color) === -1) {
            vm.checkedColors.push(color);
        } else {
            vm.checkedColors.splice(vm.checkedColors.indexOf(color), 1);
        }
        vm.formData.color_ids = vm.checkedColors;
    };
    

    My Html code:

    <div class="checkbox" ng-repeat="color in productColors">
        <label>
            <input type="checkbox"
                   ng-checked="checkedColors.indexOf(color) != -1"
                   ng-click="toggleColor(color)"/>
            <% color.title %>
        </label>
    </div>
    
    <p>checkedColors Output:</p>
    <pre><% checkedColors %></pre>
    

    [Edit] Refactored code below:

    function makeCheckedOptions(objectOptions, optionObj) {
        var checkedOptions = [];
        var savedOptions = [];
    
        if (angular.isObject(optionObj)) {
            savedOptions.push(optionObj);
        } else if (angular.isArray(optionObj)) {
            angular.forEach(optionObj, function (value, key) {
                savedOptions.push(key + ':' + value);
            });
        }
    
        angular.forEach(objectOptions, function (object) {
            angular.forEach(savedOptions, function (color) {
                if (color.id === object.id) {
                    checkedOptions.push(object);
                }
            });
        });
    
        return checkedOptions;
    }
    

    And call new method as below:

    vm.checkedColors = makeCheckedOptions(productColors, vm.formData.color_ids);
    

    That's it!

    0 讨论(0)
  • 2020-11-22 06:11

    I like Yoshi's answer. I enhanced it so You can use the same function for multiple lists.

    <label ng-repeat="fruitName in fruits">
    <input
    type="checkbox"
    name="selectedFruits[]"
    value="{{fruitName}}"
    ng-checked="selection.indexOf(fruitName) > -1"
    ng-click="toggleSelection(fruitName, selection)"> {{fruitName}}
    </label>
    
    
    <label ng-repeat="veggieName in veggies">
    <input
    type="checkbox"
    name="selectedVeggies[]"
    value="{{veggieName}}"
    ng-checked="veggieSelection.indexOf(veggieName) > -1"
    ng-click="toggleSelection(veggieName, veggieSelection)"> {{veggieName}}
    </label>
    
    
    
    app.controller('SimpleArrayCtrl', ['$scope', function SimpleArrayCtrl($scope) {
      // fruits
      $scope.fruits = ['apple', 'orange', 'pear', 'naartjie'];
      $scope.veggies = ['lettuce', 'cabbage', 'tomato']
      // selected fruits
      $scope.selection = ['apple', 'pear'];
      $scope.veggieSelection = ['lettuce']
      // toggle selection for a given fruit by name
      $scope.toggleSelection = function toggleSelection(selectionName, listSelection) {
        var idx = listSelection.indexOf(selectionName);
    
        // is currently selected
        if (idx > -1) {
          listSelection.splice(idx, 1);
        }
    
        // is newly selected
        else {
          listSelection.push(selectionName);
        }
      };
    }]);
    

    http://plnkr.co/edit/KcbtzEyNMA8s1X7Hja8p?p=preview

    0 讨论(0)
  • 2020-11-22 06:11
      <div ng-app='app' >
        <div ng-controller='MainCtrl' >
           <ul> 
           <li ng-repeat="tab in data">
             <input type='checkbox' ng-click='change($index,confirm)' ng-model='confirm' />
             {{tab.name}} 
             </li>
         </ul>
        {{val}}
       </div>
     </div>
    
    
    var app = angular.module('app', []);
     app.controller('MainCtrl',function($scope){
     $scope.val=[];
      $scope.confirm=false;
      $scope.data=[
       {
         name:'vijay'
         },
        {
          name:'krishna'
        },{
          name:'Nikhil'
         }
        ];
        $scope.temp;
       $scope.change=function(index,confirm){
         console.log(confirm);
        if(!confirm){
         ($scope.val).push($scope.data[index]);   
        }
        else{
        $scope.temp=$scope.data[index];
            var d=($scope.val).indexOf($scope.temp);
            if(d!=undefined){
             ($scope.val).splice(d,1);
            }    
           }
         }   
       })
    
    0 讨论(0)
提交回复
热议问题