web-dev-qa-db-fra.com

Validation de la case à cocher du groupe AngularJS

J'ai une liste de cases à cocher, dont au moins une est obligatoire. J'ai essayé d'y parvenir via la validation AngularJS, mais j'ai eu beaucoup de difficulté. Ci-dessous mon code:

// Code goes here for js 

var app = angular.module('App', []);

function Ctrl($scope) {
  $scope.formData = {};
  $scope.formData.selectedGender = '';
  $scope.gender = [{
    'name': 'Male',
    'id': 1
  }, {
    'name': 'Female',
    'id': 2
  }];
  $scope.formData.selectedFruits = {};
  $scope.fruits = [{
    'name': 'Apple',
    'id': 1
  }, {
    'name': 'Orange',
    'id': 2
  }, {
    'name': 'Banana',
    'id': 3
  }, {
    'name': 'Mango',
    'id': 4
  }, ];
  $scope.submitForm = function() {

  }
}
// Code goes here for html
<!doctype html>
<html ng-app="App">

<head>
  <!-- css file -->
  <!--App file -->
  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js"></script>
  <!-- External file -->
</head>

<body>
  <div ng-controller="Ctrl">
    <form class="Scroller-Container">
      <div ng-app>

        <form class="Scroller-Container" ng-submit="submit()" ng-controller="Ctrl">
          <div>
            What would you like?
            <div ng-repeat="(key, val) in fruits">
              <input type="checkbox" ng-model="formData.selectedFruits[val.id]" name="group[]" id="group[{{val.id}}]" required />{{val.name}}
            </div>
            <br />
            <div ng-repeat="(key, val) in gender">
              <input type="radio" ng-model="$parent.formData.selectedGender" name="formData.selectedGender" id="{{val.id}}" value="{{val.id}}" required />{{val.name}}
            </div>
            <br />
          </div>
          <pre>{{formData.selectedFruits}}</pre>
          <input type="submit" id="submit" value="Submit" />
        </form>
      </div>
      <br>
    </form>
  </div>
</body>

</html>

Voici le code dans plunker: http://plnkr.co/edit/Bz9yhSoPYUNzFDpfASwt?p=preview Quelqu'un l'a-t-il déjà fait sur AngularJS? Rendre les cases à cocher obligatoires me force à sélectionner toutes les valeurs des cases à cocher. Ce problème n’est pas non plus documenté dans la documentation AngularJS.

52
Pradeep Jaiswar

Si vous souhaitez exiger la sélection d'au moins un élément du groupe, vous pouvez définir l'attribut obligatoire dynamique avec ng-required.

Pour les boutons radio de genre, ce serait facile:

<input
    type="radio"
    ng-model="formData.selectedGender"
    value="{{val.id}}"
    ng-required="!formData.selectedGender"
>

Le groupe de cases à cocher serait aussi facile si vous utilisiez un tableau pour stocker les fruits sélectionnés (il suffit de vérifier la longueur du tableau), mais avec object il est nécessaire de vérifier si l'une des valeurs est définie sur true avec le filtre ou la fonction dans le contrôleur:

$scope.someSelected = function (object) {
  return Object.keys(object).some(function (key) {
    return object[key];
  });
}
<input
    type="checkbox"
    value="{{val.id}}"
    ng-model="formData.selectedFruits[val.id]"
    ng-required="!someSelected(formData.selectedFruits)"
>

Mise à jour:

const someSelected = (object = {}) => Object.keys(object).some(key => object[key])

Gardez également à l'esprit qu'il renverra false si la valeur est 0.

101
Klaster_1

Merci à Klaster_1 pour la réponse acceptée. Je me suis inspiré de cela en utilisant ng-change Sur les entrées de case à cocher pour définir une variable de portée locale, qui serait utilisée comme expression ng-required. Cela empêche l'exécution de someSelected() sur chaque résumé.

Voici un exemple montrant ceci: http://embed.plnkr.co/ScqA4aqno5XFSp9n3q6d/

Voici le HTML et JS pour la postérité.

<!DOCTYPE html>
<html ng-app="App">

<head>
  <meta charset="utf-8" />
  <script data-require="[email protected]" data-semver="1.4.9" src="https://code.angularjs.org/1.4.9/angular.js"></script>
  <script src="script.js"></script>
</head>

<body>
  <div ng-controller="AppCtrl">
    <form class="Scroller-Container" name="multipleCheckbox" novalidate="">
      <h3>What would you like?</h3>
      <div ng-repeat="fruit in fruits">
        <input type="checkbox" ng-model="formData.selectedFruits[fruit.name]" ng-change="checkboxChanged()" ng-required="!someSelected" /> {{fruit.name}}
      </div>
      <p style="color: red;" ng-show="multipleCheckbox.$error.required">You must choose one fruit</p>
    </form>
    <pre>Fruits model:
{{formData.selectedFruits | json}}</pre>
  </div>
</body>

</html>
angular
  .module('App', [])
  .controller('AppCtrl', function($scope) {

    var selectedFruits = {
      Mango: true
    };

    var calculateSomeSelected = function() {
      $scope.someSelected = Object.keys(selectedFruits).some(function(key) {
        return selectedFruits[key];
      });
    };

    $scope.formData = {
      selectedFruits: selectedFruits
    };

    $scope.fruits = [{
      'name': 'Apple'
    }, {
      'name': 'Orange'
    }, {
      'name': 'Banana'
    }, {
      'name': 'Mango'
    }];

    $scope.checkboxChanged = calculateSomeSelected;

    calculateSomeSelected();
  });
2
Tom Spencer

OK peut-être très tard pour le parti, mais si vous regardez un tableau d'objets, la solution consistant à vérifier la longueur du tableau d'objets sélectionnés a fonctionné pour moi.
HTML

<div ng-repeat="vehicle in vehicles">
    <input type="checkbox" name="car" ng-model="car.ids[vehicle._id]" ng-required=" car.objects.length <= 0"> {{vehicle.model}} {{vehicle.brand}} <b>{{vehicle.geofenceName}}</b>
</div>

JS

$scope.vehicles = [{},{}] // Your array of objects;
$scope.car = {
    ids: {},
    objects: []
};

$scope.$watch(function() {
    return $scope.car.ids;
}, function(value) {
    $scope.car.objects = [];
    angular.forEach($scope.car.ids, function(value, key) {
        value && $scope.car.objects.Push(getCategoryById(key));
    });
}, true);

function getCategoryById(id) {
    for (var i = 0; i < $scope.vehicles.length; i++) {
        if ($scope.vehicles[i]._id == id) {
            return $scope.vehicles[i];
        }
    }
}

Je comprends ce qui se passe dans cette solution si vous cochez toutes les options des cases à cocher pour savoir laquelle est cliquée. Mais de ce que je sais, c’est de loin la solution la plus simple (à comprendre et à mettre en œuvre) et elle fonctionne à merveille si vous savez que vos options seront limitées. Pour une solution optimisée plus de temps. Vérifiez les réponses ci-dessus.

2
Saras Arya

Nous pouvons réaliser vos besoins sans parcourir toutes les instances de cases à cocher. Voici l exemple de code

<script>
angular.module('atLeastOneExample', [])
.controller('ExampleController', ['$scope', function($scope) {
  $scope.e = function(s){
    eval(s);
  };
}]);
</script>

Ici, j’enveloppe la fonction javascript eval dans la fonction "e" pour y accéder.

<form name="myForm" ng-controller="ExampleController" ng-init="c=0">
  <label>
      Value1: <input type="checkbox" ng-model="checkboxModel.value[0]" ng-change="e('($scope.checkboxModel.value[0])?$scope.c++:$scope.c--')"/>
  </label><br/>
  <label>
      Value2: <input type="checkbox" ng-model="checkboxModel.value[1]" ng-change="e('($scope.checkboxModel.value[1])?$scope.c++:$scope.c--')"/>
  </label><br/>
  value = {{checkboxModel.value}}<br/>
  isAtLeastOneChecked = {{c>0}}
</form>
1
Vivek Kumar