简体   繁体   中英

AngularJS: single select between multiple checkbox

I am trying to force a single-selection on checkboxes, similar to a html "select"

I have a html simple table:

<tr ng-repeat="subscription in entities">
    <td>
        <input type="checkbox" ng-checked="isChecked(subscription)" ng-click="toggleSelection(subscription)"/>
    </td>
</tr> 

Then I have some simple controller functions for those directives above:

$scope.isChecked = function(entity) {
    return $scope.checkedEntity === entity;
};

$scope.toggleSelection = function(entity) {
    entity.checked = !entity.checked;
    if (entity.checked) {
        $scope.checkedEntity = entity;
    } else {
        $scope.checkedEntity = null;
    }
};

Unfortunately it doesn't work, and I think I just discovered why.... the ng-click has 0 priority, vs 100 for ng-checked.

Is there an elegant solution for this problem?

Bind ng-model to subscription.checked , and have ng-click uncheck all subscriptions except the one clicked. Since these are checkboxes, the one clicked will toggle itself.

<tr ng-repeat="subscription in entities">
  <td>
    <input ng-model="subscription.checked" ng-click="updateSelection($index, entities)" type="checkbox" />
  </td>
</tr>

You can use a plain for loop, but angular's forEach allows us to alias each item as subscription and improve readability:

$scope.updateSelection = function(position, entities) {
  angular.forEach(entities, function(subscription, index) {
    if (position != index) 
      subscription.checked = false;
  });
}

Here is a working demo: http://plnkr.co/edit/XD7r6PoTWpI4cBjdIZtv?p=preview

 <!DOCTYPE html> <html> <head> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script> <script> angular.module('app', []).controller('appc', ['$scope', function($scope) { $scope.selected = 'other'; } ]); </script> </head> <body ng-app="app" ng-controller="appc"> <label>SELECTED: {{selected}}</label> <div> <input type="checkbox" ng-checked="selected=='male'" ng-true-value="'male'" ng-model="selected">Male <br> <input type="checkbox" ng-checked="selected=='female'" ng-true-value="'female'" ng-model="selected">Female <br> <input type="checkbox" ng-checked="selected=='other'" ng-true-value="'other'" ng-model="selected">Other </div> </body> </html> 

I have used the below code to achieve the similar functionality. Trick is to use ng-click which can yield this pretty nicely. checkbox-1 & checkbox-2 are boolean in nature.

<form>
    <input type="checkbox" ng-click="checkbox-2 = false" ng-model="checkbox-1" >
    <input type="checkbox" ng-click="checkbox-1 = false" ng-model="checkbox-2" >
</form>

Off the top of my head, I'd suggest one of three options for you.

  1. Write a directive that will set up the checkboxes for you and manage the state within them. This isn't ideal, because you're turning a rule about your model (only one subscription should be checked) into DOM manipulation problem.
  2. Structure your model such that only one subscription is ever marked active. This is tricky, because modifying the model on a change will kick off another digest cycle, not what you want.
  3. Use radio buttons instead of checkboxes. That will get you the modality you want. :-P

I'd go with option 3--I'm always a fan of taking advantage of native input elements.

<tr ng-repeat="subscription in entities">
<td><input type="radio"
   ng-model="selection"
   name="subscriptionRadio"
   value="{{subscription}}"/>
</td> 
</tr>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM