Wie binde ich mit AngularJS an eine Liste von Kontrollkästchenwerten?


670

Ich habe ein paar Kontrollkästchen:

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

Ich möchte an eine Liste in meinem Controller binden, sodass der Controller bei jedem Ändern eines Kontrollkästchens eine Liste aller aktivierten Werte führt, z. ['apple', 'pear'] .

ng-model scheint nur in der Lage zu sein, den Wert eines einzelnen Kontrollkästchens an eine Variable im Controller zu binden.

Gibt es eine andere Möglichkeit, die vier Kontrollkästchen an eine Liste im Controller zu binden?


23
Muss es eine Liste sein? Würde ein Objekt funktionieren?: <input type='checkbox' ng-model="checkboxes.apple">Usw. Modell wäre: {"Apfel": wahr, "orange": falsch, "Birne": wahr, "naartjie": wahr}
Mark Rajcok

2
Versuchen Sie die Anweisung in diesem Repo
Vikas Gautam

1
Achten Sie darauf, über die akzeptierte Antwort hinauszuschauen. Es gibt noch eine andere Antwort, die meiner Meinung nach viel eleganter ist.
Jason Swett

3
naartjie!? Das verrät dir nur Boet! : D
Piotr Kula

1
@ppumkin hehe gerade gesehen. Sie haben Recht: D
Nickponline

Antworten:


927

Es gibt zwei Möglichkeiten, um dieses Problem anzugehen. Verwenden Sie entweder ein einfaches Array oder ein Array von Objekten. Jede Lösung hat Vor- und Nachteile. Nachfolgend finden Sie für jeden Fall eine.


Mit einem einfachen Array als Eingabedaten

Der HTML-Code könnte folgendermaßen aussehen:

<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>

Und der entsprechende Controller-Code wäre:

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);
    }
  };
}]);

Vorteile : Einfache Datenstruktur und das Umschalten nach Namen sind einfach zu handhaben

Nachteile : Hinzufügen / Entfernen ist umständlich, da zwei Listen (Eingabe und Auswahl) verwaltet werden müssen


Mit einem Objektarray als Eingabedaten

Der HTML-Code könnte folgendermaßen aussehen:

<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>

Und der entsprechende Controller-Code wäre:

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);
}]);

Vorteile : Hinzufügen / Entfernen ist sehr einfach

Nachteile : Eine etwas komplexere Datenstruktur und das Umschalten nach Namen ist umständlich oder erfordert eine Hilfsmethode


Demo : http://jsbin.com/ImAqUC/1/


10
Zu Ihrer Information, anstatt $ filter zu injizieren, können Sie filterFilter injizieren und dann wie folgt verwenden: return filterFilter ($ scope.fruits, {checked: true}); Eingebaute und benutzerdefinierte Filter werden beim $ Injektor mit dem Namen filterNameFilter registriert ("filterName" sollte kursiv sein) - $ filterProvider docs
Mark Rajcok

24
value="{{fruit.name}}"und ng-checked="fruit.checked"sind überflüssig, da ng-model verwendet wird.
Mark Rajcok

3
Ich habe festgestellt, dass im Modell nicht "markiert" angegeben werden muss. Angular setzt die Eigenschaft automatisch :)
Daveoncode

3
Sollte ng-change anstelle von ng-click verwenden, da es Randfälle besser behandelt.
Amccausl

2
@ViktorMolokostov Das wäre nur nützlich, wenn Sie das Formular traditionell einreichen würden . Dies bedeutet, dass es an den Aktionshandler gesendet wird (ein serverseitiges Skript). Mit PHP erstellt ein Formularelement mit einem solchen Namen (in eckigen Klammern) ein Array in den Anforderungsdaten. Auf diese Weise können Sie leicht mit den ausgewählten Früchten umgehen.
Yoshi

406

Eine einfache Lösung:

<div ng-controller="MainCtrl">
  <label ng-repeat="(color,enabled) in colors">
      <input type="checkbox" ng-model="colors[color]" /> {{color}} 
  </label>
  <p>colors: {{colors}}</p>
</div>

<script>
  var app = angular.module('plunker', []);

  app.controller('MainCtrl', function($scope){
      $scope.colors = {Blue: true, Orange: true};
  });
</script>

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


57
@kolypto - das ist definitiv die Antwort. Ich habe es für Leute (wie mich) umgeschrieben, die mit Objekten arbeiten: plnkr.co/edit/cqsADe8lKegsBMgWMyB8?p=preview
Kyle

5
Ich mache es genauso wie Sie, aber was macht das Aktivierte in (color,enabled) in colors?
Sebastian

3
@Sebastian, da colorses sich um ein Objekt handelt, erhalten Sie beim Iterieren Paare von (key,value).
kolypto

10
Obwohl mir diese Antwort sehr gefällt! Ich denke, es gibt ein großes Problem bei der Verwendung von Objekten als Datenquelle. Das heißt, da per Definition die Reihenfolge der Objekteigenschaften nicht definiert ist, kann beim Anzeigen der Kontrollkästchen keine bestimmte Reihenfolge angegeben werden. Immer noch +1;)
Yoshi

2
colorssollte benannt werden isSelected, ist es viel einfacher zu lesen isSelected[color]alscolors[color]
Dmitri Zaitsev

86
<input type='checkbox' ng-repeat="fruit in fruits"
  ng-checked="checkedFruits.indexOf(fruit) != -1" ng-click="toggleCheck(fruit)">

.

function SomeCtrl ($scope) {
    $scope.fruits = ["apple, orange, pear, naartjie"];
    $scope.checkedFruits = [];
    $scope.toggleCheck = function (fruit) {
        if ($scope.checkedFruits.indexOf(fruit) === -1) {
            $scope.checkedFruits.push(fruit);
        } else {
            $scope.checkedFruits.splice($scope.checkedFruits.indexOf(fruit), 1);
        }
    };
}

2
Ich liebe es, wie einfach das ist, genau das, wonach ich suche (obwohl ich zugeben muss, dass die @ vitalets-Direktive erstaunlich ist). Ich habe Umurs Code ein wenig geändert, um diese Geige zu erstellen: jsfiddle.net/samurai_jane/9mwsbfuc
samurai_jane

Ich mache die Worte der Samurai Jane zu meinen! Wie einfach es war, genau das zu zeigen, was ich brauchte! :)
Francis Rodrigues

81

Hier ist eine kurze, wiederverwendbare Direktive, die genau das zu tun scheint, wonach Sie suchen. Ich habe es einfach genannt checkList. Es aktualisiert das Array, wenn sich die Kontrollkästchen ändern, und aktualisiert die Kontrollkästchen, wenn sich das Array ändert.

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);
    }
  };
});

Hier ist ein Controller und eine Ansicht, die zeigt, wie Sie ihn möglicherweise verwenden.

<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);
  };
});

(Die Schaltflächen zeigen, dass durch Ändern des Arrays auch die Kontrollkästchen aktualisiert werden.)

Schließlich ist hier ein Beispiel für die Richtlinie in Aktion auf Plunker: http://plnkr.co/edit/3YNLsyoG4PIBW6Kj7dRK?p=preview


2
Danke Brandon, das hat genau das getan, was ich wollte (und genau das, wonach die Frage im Gegensatz zu den anderen Antworten gefragt hat). Die einzige Änderung, die ich vorgenommen habe, war, Ihre "elem.on ('change', function () ..." in "elem.bind ('change', function () ...") zu ändern, um die Abhängigkeit von jQuery zu entfernen .
Jonathan Moffatt

Das ist ziemlich ordentlich, zerstört aber irgendwie meine Fähigkeit, ng-disabled zu verwenden :( Kann ich das irgendwie beheben?
Nikolaj Dam Larsen

Super nützlich! Und arbeitete sogar für mich mit Objekten anstelle von Arrays sowohl für die Quellliste als auch für die Datenliste!
SteveShaffer

Ich stimme allen zu. Dieser ist der nützlichste und zweifellos wiederverwendbare !! Danke für die gute Arbeit. :)
maksbd19

2
Wenn Sie Probleme mit AngularJS> = 1.4.4 haben, überprüfen Sie github.com/angular/angular.js/issues/13037 : Ersetzen Sie value: '@'durchvalue: '=ngValue'
tanguy_k

66

Basierend auf den Antworten in diesem Thread habe ich eine Checklistenmodell- Direktive erstellt, die alle Fälle abdeckt:

  • einfache Anordnung von Grundelementen
  • Array von Objekten (ID oder ganzes Objekt auswählen)
  • Iteration der Objekteigenschaften

Für den Thema-Starter-Fall wäre es:

<label ng-repeat="fruit in ['apple', 'orange', 'pear', 'naartjie']">
    <input type="checkbox" checklist-model="selectedFruits" checklist-value="fruit"> {{fruit}}
</label>

Das sieht so aus, wie ich es brauche. Gibt es eine Möglichkeit, die Verwendung beim asynchronen Abrufen der Daten zu erläutern? Dieser Teil ist für mich verwirrend.
Dan Cancro

Nachdem Sie die Daten asynchron erhalten haben, ändern Sie einfach das Checlist-Modell im Bereich, im obigen Beispiel selectedFruits.
Adrian Ber

11

Die Verwendung einer Zeichenfolge von $indexkann helfen, eine Hashmap ausgewählter Werte zu verwenden:

<ul>
    <li ng-repeat="someItem in someArray">
        <input type="checkbox" ng-model="someObject[$index.toString()]" />
    </li>
</ul>

Auf diese Weise wird das ng-model-Objekt mit dem Schlüssel aktualisiert, der den Index darstellt.

$scope.someObject = {};

Nach einer Weile $scope.someObjectsollte ungefähr so ​​aussehen:

$scope.someObject = {
     0: true,
     4: false,
     1: true
};

Diese Methode funktioniert nicht in allen Situationen, ist jedoch einfach zu implementieren.


Dies ist eine sehr elegante Lösung und passt zu meinem Fall (mit AJAX)
Stephan Ryer

verwendet die
Kussmethode

8

Da Sie eine Antwort akzeptiert haben, in der keine Liste verwendet wurde, gehe ich davon aus, dass die Antwort auf meine Kommentarfrage "Nein, es muss keine Liste sein" lautet. Ich hatte auch den Eindruck, dass Sie möglicherweise die HTML-Serverseite gerendert haben, da "geprüft" in Ihrem Beispiel-HTML vorhanden ist (dies wäre nicht erforderlich, wenn ng-model zum Modellieren Ihrer Kontrollkästchen verwendet würde).

Folgendes habe ich mir gedacht, als ich die Frage gestellt habe, vorausgesetzt, Sie haben die HTML-Serverseite generiert:

<div ng-controller="MyCtrl" 
 ng-init="checkboxes = {apple: true, orange: false, pear: true, naartjie: false}">
    <input type="checkbox" ng-model="checkboxes.apple">apple
    <input type="checkbox" ng-model="checkboxes.orange">orange
    <input type="checkbox" ng-model="checkboxes.pear">pear
    <input type="checkbox" ng-model="checkboxes.naartjie">naartjie
    <br>{{checkboxes}}
</div>

Mit ng-init können serverseitig generiertes HTML zunächst bestimmte Kontrollkästchen setzen.

Geige .


8

Ich denke, die einfachste Problemumgehung wäre die Verwendung von 'select' mit 'multiple':

<select ng-model="selectedfruit" multiple ng-options="v for v in fruit"></select>

Andernfalls müssen Sie die Liste verarbeiten, um die Liste zu erstellen (indem $watch()Sie das Modellarray mit Kontrollkästchen binden).


3
Er bittet um eine Checkbox-Liste, und dennoch erzählen Sie ihm von der Auswahl mit Optionen. Welches ist ganz anders.
CrazySabbath

@ CrazySabbath: dennoch verstehen Sie nicht, dass er eine alternative Lösung vorschlägt und diese Antwort 6 anderen Menschen als "alternative Lösung"
half

5

Ich habe Yoshis akzeptierte Antwort angepasst, um mit komplexen Objekten (anstelle von Zeichenfolgen) umzugehen.

HTML

<div ng-controller="TestController">
    <p ng-repeat="permission in allPermissions">
        <input type="checkbox" ng-checked="selectedPermissions.containsObjectWithProperty('id', permission.id)" ng-click="toggleSelection(permission)" />
        {{permission.name}}
    </p>

    <hr />

    <p>allPermissions: | <span ng-repeat="permission in allPermissions">{{permission.name}} | </span></p>
    <p>selectedPermissions: | <span ng-repeat="permission in selectedPermissions">{{permission.name}} | </span></p>
</div>

JavaScript

Array.prototype.indexOfObjectWithProperty = function(propertyName, propertyValue)
{
    for (var i = 0, len = this.length; i < len; i++) {
        if (this[i][propertyName] === propertyValue) return i;
    }

    return -1;
};


Array.prototype.containsObjectWithProperty = function(propertyName, propertyValue)
{
    return this.indexOfObjectWithProperty(propertyName, propertyValue) != -1;
};


function TestController($scope)
{
    $scope.allPermissions = [
    { "id" : 1, "name" : "ROLE_USER" },
    { "id" : 2, "name" : "ROLE_ADMIN" },
    { "id" : 3, "name" : "ROLE_READ" },
    { "id" : 4, "name" : "ROLE_WRITE" } ];

    $scope.selectedPermissions = [
    { "id" : 1, "name" : "ROLE_USER" },
    { "id" : 3, "name" : "ROLE_READ" } ];

    $scope.toggleSelection = function toggleSelection(permission) {
        var index = $scope.selectedPermissions.indexOfObjectWithProperty('id', permission.id);

        if (index > -1) {
            $scope.selectedPermissions.splice(index, 1);
        } else {
            $scope.selectedPermissions.push(permission);
        }
    };
}

Arbeitsbeispiel: http://jsfiddle.net/tCU8v/


1
Sie sollten niemals eine <input type="checkbox">ohne Verpackung oder Matching haben <label>! Jetzt müssen Ihre Benutzer auf das eigentliche Kontrollkästchen anstatt auf den Text neben dem Kontrollkästchen klicken, was viel schwieriger und benutzerfreundlicher ist.
Scott

5

Eine andere einfache Anweisung könnte lauten:

var appModule = angular.module("appModule", []);

appModule.directive("checkList", [function () {
return {
    restrict: "A",
    scope: {
        selectedItemsArray: "=",
        value: "@"
    },
    link: function (scope, elem) {
        scope.$watchCollection("selectedItemsArray", function (newValue) {
            if (_.contains(newValue, scope.value)) {
                elem.prop("checked", true);
            } else {
                elem.prop("checked", false);
            }
        });
        if (_.contains(scope.selectedItemsArray, scope.value)) {
            elem.prop("checked", true);
        }
        elem.on("change", function () {
            if (elem.prop("checked")) {
                if (!_.contains(scope.selectedItemsArray, scope.value)) {
                    scope.$apply(
                        function () {
                            scope.selectedItemsArray.push(scope.value);
                        }
                    );
                }
            } else {
                if (_.contains(scope.selectedItemsArray, scope.value)) {
                    var index = scope.selectedItemsArray.indexOf(scope.value);
                    scope.$apply(
                        function () {
                            scope.selectedItemsArray.splice(index, 1);
                        });
                }
            }
            console.log(scope.selectedItemsArray);
        });
    }
};
}]);

Der Controller:

appModule.controller("sampleController", ["$scope",
  function ($scope) {
    //#region "Scope Members"
    $scope.sourceArray = [{ id: 1, text: "val1" }, { id: 2, text: "val2" }];
    $scope.selectedItems = ["1"];
    //#endregion
    $scope.selectAll = function () {
      $scope.selectedItems = ["1", "2"];
  };
    $scope.unCheckAll = function () {
      $scope.selectedItems = [];
    };
}]);

Und der HTML:

<ul class="list-unstyled filter-list">
<li data-ng-repeat="item in sourceArray">
    <div class="checkbox">
        <label>
            <input type="checkbox" check-list selected-items-array="selectedItems" value="{{item.id}}">
            {{item.text}}
        </label>
    </div>
</li>

Ich füge auch einen Plunker hinzu: http://plnkr.co/edit/XnFtyij4ed6RyFwnFN6V?p=preview


5

Die folgende Lösung scheint eine gute Option zu sein:

<label ng-repeat="fruit in fruits">
  <input
    type="checkbox"
    ng-model="fruit.checked"
    ng-value="true"
  > {{fruit.fruitName}}
</label>

Und im Controller-Modell wird der Wert fruitsso sein

$scope.fruits = [
  {
    "name": "apple",
    "checked": true
  },
  {
    "name": "orange"
  },
  {
    "name": "grapes",
    "checked": true
  }
];

Je mehr ich mir diese Beispiele anschaue, desto mehr muss ich mein Array auf ein Array von Objekten abbilden.
Winnemucca

4

Sie müssen nicht den ganzen Code schreiben. AngularJS hält das Modell und die Kontrollkästchen einfach mithilfe von ngTrueValue und ngFalseValue synchron

Codepen hier: http://codepen.io/paulbhartzog/pen/kBhzn

Code-Auszug:

<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>

Dies ist nicht das, wonach OP verlangt.
Bfontaine

Das Binden von Kontrollkästchen an eine Liste ist das, was gefragt wurde und was ich getan habe. Das Array kann an die Anwendung angepasst werden. Der Punkt ist, dass die Kontrollkästchen gebunden sind. ngTrueValue und ngFalseValue können auch verwendet werden, um einem zweiten Array zuzuordnen, das nur andere Attribute wie Namen auflistet.
Paul B. Hartzog

OP möchte eine Liste der überprüften Werte, nicht eine Liste aller Werte, die aktiviert und deaktiviert sind.
Bfontaine

4

Schauen Sie sich diese Anweisung an, mit der Listen von Kontrollkästchen effektiv verwaltet werden. Ich hoffe es funktioniert bei dir. CheckList-Modell


4

Es gibt eine Möglichkeit, direkt am Array zu arbeiten und gleichzeitig das ng-Modell zu verwenden ng-model-options="{ getterSetter: true }" .

Der Trick besteht darin, eine Getter / Setter-Funktion in Ihrem ng-Modell zu verwenden. Auf diese Weise können Sie ein Array als Ihr reales Modell verwenden und die Booleschen Werte im Modell der Eingabe "fälschen":

<label ng-repeat="fruitName in ['apple', 'orange', 'pear', 'naartjie']">
  <input
    type="checkbox"
    ng-model="fruitsGetterSetterGenerator(fruitName)"
    ng-model-options="{ getterSetter: true }"
  > {{fruitName}}
</label>

$scope.fruits = ['apple', 'pear']; // pre checked

$scope.fruitsGetterSetterGenerator = function(fruitName){
    return function myGetterSetter(nowHasFruit){
        if (nowHasFruit !== undefined){

            // Setter
            fruitIndex = $scope.fruits.indexOf(fruit);
            didHaveFruit = (fruitIndex !== -1);
            mustAdd = (!didHaveFruit && nowHasFruit);
            mustDel = (didHaveFruit && !nowHasFruit);
            if (mustAdd){
                $scope.fruits.push(fruit);
            }
            if (mustDel){
                $scope.fruits.splice(fruitIndex, 1);
            }
        }
        else {
            // Getter
            return $scope.user.fruits.indexOf(fruit) !== -1;
        }
    }
}

CAVEAT Sie sollten diese Methode nicht verwenden, wenn Ihre Arrays so groß sind wiemyGetterSetter dies häufig genannt wird.

Weitere Informationen hierzu finden Sie unter https://docs.angularjs.org/api/ng/directive/ngModelOptions .


3

Ich mag Yoshis Antwort. Ich habe es erweitert, damit Sie dieselbe Funktion für mehrere Listen verwenden können.

<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


3

Wenn Sie mehrere Kontrollkästchen im selben Formular haben

Der Controller-Code

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

Code anzeigen

<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>        

3

Inspiriert von Yoshis Beitrag oben. Hier ist die plnkr .

(function () {
   
   angular
      .module("APP", [])
      .controller("demoCtrl", ["$scope", function ($scope) {
         var dc = this
         
         dc.list = [
            "Selection1",
            "Selection2",
            "Selection3"
         ]

         dc.multipleSelections = []
         dc.individualSelections = []
         
         // 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.
         dc.addOrRemove = 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)
               }
            }
         }
         
      }])
   
})()
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" 
            ng-checked="dc.multipleSelections.indexOf(thing) > -1"
            ng-click="dc.addOrRemove(dc.multipleSelections, thing, true)"
         > {{thing}}
      </label>
      
      <p>
         dc.multipleSelections :- {{dc.multipleSelections}}
      </p>
      
      <hr>
      
      <h4>Individual Selections</h4>
      <label ng-repeat="thing in dc.list">
         <input 
            type="checkbox" 
            ng-checked="dc.individualSelections.indexOf(thing) > -1"
            ng-click="dc.addOrRemove(dc.individualSelections, thing, false)"
         > {{thing}}
      </label>
      
      <p>
         dc.invidualSelections :- {{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>


3

Basierend auf meinem anderen Beitrag hier ich eine wiederverwendbare Richtlinie erstellt.

Überprüfen Sie das GitHub-Repository

(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>


3

Im HTML-Code (vorausgesetzt, die Kontrollkästchen befinden sich in der ersten Spalte jeder Zeile in einer Tabelle).

<tr ng-repeat="item in fruits">
    <td><input type="checkbox" ng-model="item.checked" ng-click="getChecked(item)"></td>
    <td ng-bind="fruit.name"></td>
    <td ng-bind="fruit.color"></td>
    ...
</tr>

In der controllers.jsDatei:

// The data initialization part...
$scope.fruits = [
    {
      name: ....,
      color:....
    },
    {
      name: ....,
      color:....
    }
     ...
    ];

// The checked or not data is stored in the object array elements themselves
$scope.fruits.forEach(function(item){
    item.checked = false;
});

// The array to store checked fruit items
$scope.checkedItems = [];

// Every click on any checkbox will trigger the filter to find checked items
$scope.getChecked = function(item){
    $scope.checkedItems = $filter("filter")($scope.fruits,{checked:true});
};

3

Hier ist noch eine andere Lösung. Der Vorteil meiner Lösung:

  • Es werden keine zusätzlichen Uhren benötigt (was sich auf die Leistung auswirken kann).
  • Es ist kein Code im Controller erforderlich, um ihn sauber zu halten
  • Der Code ist noch etwas kurz
  • Die Wiederverwendung an mehreren Stellen erfordert nur sehr wenig Code, da es sich nur um eine Direktive handelt

Hier ist die Richtlinie:

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;
            });
        }
    }
}

Am Ende benutze es dann einfach so:

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

Und das ist alles was es gibt. Die einzige Ergänzung ist das checkbox-array-setAttribut.


3

Sie können AngularJS und jQuery kombinieren. Beispielsweise müssen Sie $scope.selected = [];im Controller ein Array definieren .

<label ng-repeat="item in items">
    <input type="checkbox" ng-model="selected[$index]" ng-true-value="'{{item}}'">{{item}}
</label>

Sie können ein Array erhalten, das die ausgewählten Elemente besitzt. Mit der Methode alert(JSON.stringify($scope.selected))können Sie die ausgewählten Elemente überprüfen.


Perfekt! ... dies ist die einfachste Lösung mit einem Array, das kein Objekt ist
Mario Campa

3
Kombinieren Sie nicht Jquery und Angular
Jens Alenius

Dies führt zu Löchern im ausgewählten Array. Überprüfen Sie diesen Beitrag
Vikas Gautam

2
  <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);
        }    
       }
     }   
   })

1

Schauen Sie sich das an: Checklistenmodell .

Es funktioniert mit JavaScript-Arrays und -Objekten und kann statische HTML-Kontrollkästchen ohne ng-repeat verwenden

<label><input type="checkbox" checklist-model="roles" value="admin"> Administrator</label>
<label><input type="checkbox" checklist-model="roles" value="customer"> Customer</label>
<label><input type="checkbox" checklist-model="roles" value="guest"> Guest</label>
<label><input type="checkbox" checklist-model="roles" value="user"> User</label>

Und die JavaScript-Seite:

var app = angular.module("app", ["checklist-model"]);
app.controller('Ctrl4a', function($scope) {
    $scope.roles = [];
});

1

Eine einfache HTML-Methode:

<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')">


1

Anhand dieses Beispiels des @Umur Kontacı denke ich daran, ausgewählte Daten in einem anderen Objekt / Array wie einer Bearbeitungsseite abzufangen.

Fangoptionen in der Datenbank

Geben Sie hier die Bildbeschreibung ein

Schalten Sie eine Option um

Geben Sie hier die Bildbeschreibung ein

Als Beispiel sind alle Farben unten aufgeführt:

{
    "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"
        }
    ]
}

Und 2 Arten von Datenobjekten arraymit einem Objekt und objectzwei / mehr Objektdaten:

  • Zwei ausgewählte Elemente wurden in der Datenbank gefangen:

    [{"id":12,"title":"Branco - #FFFFFF"},{"id":16,"title":"Roxo - #3A0858"}]
  • Ein ausgewähltes Element wurde in der Datenbank gefangen:

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

Und hier mein 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;
};

Mein 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>

[Bearbeiten] Refactored Code unten:

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;
}

Und rufen Sie die neue Methode wie folgt auf:

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

Das ist es!


1

Ich habe ein Array in den Controller eingefügt.

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

Auf das Markup habe ich so etwas wie folgendes gesetzt

<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}}

Die Ausgabe war die folgende, in der Steuerung musste ich nur überprüfen, ob es wahr oder falsch ist; wahr für geprüft, abwesend / falsch für ungeprüft.

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

Hoffe das hilft.


0

Ich denke, der folgende Weg ist klarer und nützlicher für verschachtelte ng-Wiederholungen. Schau es dir auf Plunker an .

Zitat aus diesem 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

Hier ist der jsFillde-Link für dasselbe, http://jsfiddle.net/techno2mahi/Lfw96ja6/ .

Hierbei wird die Richtlinie verwendet, die unter http://vitalets.github.io/checklist-model/ zum Download zur Verfügung steht .

Dies ist eine gute Direktive, da Ihre Anwendung diese Funktionalität häufig benötigt.

Der Code ist unten:

HTML:

<div class="container">
    <div class="ng-scope" ng-app="app" ng-controller="Ctrl1">
        <div class="col-xs-12 col-sm-6">
            <h3>Multi Checkbox List Demo</h3>
            <div class="well">  <!-- ngRepeat: role in roles -->
                <label ng-repeat="role in roles">
                    <input type="checkbox" checklist-model="user.roles" checklist-value="role"> {{role}}
                </label>
            </div>

            <br>
            <button ng-click="checkAll()">check all</button>
            <button ng-click="uncheckAll()">uncheck all</button>
            <button ng-click="checkFirst()">check first</button>
            <div>
                <h3>Selected User Roles </h3>
                <pre class="ng-binding">{{user.roles|json}}</pre>
            </div>

            <br>
            <div><b/>Provided by techno2Mahi</b></div>
        </div>

JavaScript

var app = angular.module("app", ["checklist-model"]);
app.controller('Ctrl1', function($scope) {
  $scope.roles = [
    'guest',
    'user',
    'customer',
    'admin'
  ];
  $scope.user = {
    roles: ['user']
  };
  $scope.checkAll = function() {
    $scope.user.roles = angular.copy($scope.roles);
  };
  $scope.uncheckAll = function() {
    $scope.user.roles = [];
  };
  $scope.checkFirst = function() {
    $scope.user.roles.splice(0, $scope.user.roles.length);
    $scope.user.roles.push('guest');
  };
});

Der HTML-Code ist nicht gut geformt - es gibt mehr öffnende Tags <div>als schließende </div>. Hast du etwas ausgelassen?
Peter Mortensen

0

Versuchen Sie mein Baby:

** **.

myApp.filter('inputSelected', function(){
  return function(formData){
    var keyArr = [];
    var word = [];
    Object.keys(formData).forEach(function(key){
    if (formData[key]){
        var keyCap = key.charAt(0).toUpperCase() + key.slice(1);
      for (var char = 0; char<keyCap.length; char++ ) {
        if (keyCap[char] == keyCap[char].toUpperCase()){
          var spacedLetter = ' '+ keyCap[char];
          word.push(spacedLetter);
        }
        else {
          word.push(keyCap[char]);
        }
      }
    }
    keyArr.push(word.join(''))
    word = [];
    })
    return keyArr.toString();
  }
})

** **.

Für jedes ng-Modell mit Kontrollkästchen wird dann eine Zeichenfolge aller von Ihnen ausgewählten Eingaben zurückgegeben:

<label for="Heard about ITN">How did you hear about ITN?: *</label><br>
<label class="checkbox-inline"><input ng-model="formData.heardAboutItn.brotherOrSister" type="checkbox" >Brother or Sister</label>
<label class="checkbox-inline"><input ng-model="formData.heardAboutItn.friendOrAcquaintance" type="checkbox" >Friend or Acquaintance</label>


{{formData.heardAboutItn | inputSelected }}

//returns Brother or Sister, Friend or Acquaintance
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.