使用AngularJS检查n个复选框时,禁用其余复选框

时间:2015-03-25 15:56:35

标签: angularjs

我刚刚开始学习AngularJS,所以请耐心等待。

我有一个带有列表的应用程序,该列表绑定到一组对象(D& D spells)。该列表通过绑定到对象的各种值来显示对象的所有内容。它们过滤搜索文本框(query)的值,并按拼写对象的两个属性(级别和名称)进行排序。一切正常。

<div ng-repeat="(spellKey, spellValue) in spells | groupBy:'level'">
    <a id="level-{{spellKey}}" class="anchor"></a>
    <div ng-repeat="spell in spellValue | filterEach:query | orderBy:['level','name']">
        <a id="spell-{{spell.name | replaceSpaces}}" class="anchor"></a>
        ...
    </div>
</div>

我有第二个列表,我放在我的导航栏中,它绑定到同一个数组。它只显示名称和每个名称旁边的复选框;复选框确定是否列出第一个列表中的每个对象(通过将spell.prepared设置为truefalse)。这也很好。

<div class="navbar-header">
    <form class="form-inline navbar-left col-xs-10" role="search">
        ...
    </form>
    <div class="col-xs-2">
        <!-- button that displays list of spell links and checkboxes -->
        <button type="button" id="btn-toggle-navbar" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#spell-nav">
            ...
        </button>
    </div>
    <div class="collapse navbar-collapse" id="spell-nav">
        <div class="checkbox" style="padding-bottom: 4px;">
            <label>
                <input type="checkbox" id="cbHideNonPrepared" ng-model="hideNonPrepared" />
                Hide non-prepared
            </label>
        </div>
        <div ng-repeat="(linkKey, linkValue) in spells | groupBy:'level'">
            ...
            <ul style="list-style-type: none">
                <li ng-repeat="spellLink in linkValue" class="checkbox">
                    <label>
                        <input type="checkbox" ng-model="spellLink.prepared" ng-class="{true: 'invis'}[spellLink.alwaysPrepared || spellLink.level == 0]" />
                        <a href="#spell-{{spellLink.name | replaceSpaces}}" ng-click="onSpellLinkClick($event)">{{spellLink.name}}</a>
                    </label>
                </li>
            </ul>
        </div>
    </div>
</div>

...

<!-- previous code block with added 'ng-hide' -->
<div ng-repeat="(spellKey, spellValue) in spells | groupBy:'level'">
    <a id="level-{{spellKey}}" class="anchor"></a>
    <div ng-repeat="spell in spellValue | filterEach:query | orderBy:['level','name']"
         ng-hide="hideNonPrepared && !spell.prepared">
        <a id="spell-{{spell.name | replaceSpaces}}" class="anchor"></a>
        ...
    </div>
</div>

最后,我想将允许的复选框的数量限制为$scope中指定的某个值(恰好是9,但可以是任意整数)。我还希望排除spell.alwaysPrepared == true中的任何值,但我认为我只能稍后添加filter

这是我不确定如何继续的地方。我想也许我应该设置ng-check,但我不确定是什么。

1 个答案:

答案 0 :(得分:1)

您可以使用ng-disabled在特定条件下禁用复选框。

以下是一个可能对您有用的示例。这里的关键是创建一个将在每个摘要周期调用的函数,以确定是否应禁用每个复选框。

angular.module("spells", [])
.controller("spellController", function($scope) {

  $scope.shouldDisable = function(spell) {
    return $scope.numPreparedSpells() == $scope.maxPreparedSpells && !spell.isPrepared;
  };

  $scope.spells = [
    {name: "Magic Missile", isPrepared: false},
    {name: "Lightning bolt", isPrepared: false},
    {name: "Cure Major Wounds", isPrepared: false}
  ];

  $scope.maxPreparedSpells = 2;

  $scope.numPreparedSpells = function() {
    var numPrepared = 0, len = $scope.spells.length;
    for(var i = 0; i < len; i++) {
      if ($scope.spells[i].isPrepared) {
        numPrepared++;
      }
    }

    return numPrepared;
  };
});

启用此设置后,您的拼写列表HTML可能如下所示:

<div ng-controller="spellController">
  <div ng-repeat="spell in spells">
    <input type="checkbox" ng-model="spell.isPrepared" ng-disabled="shouldDisable(spell)"/>{{spell.name}}
  </div>
</div>

Try it on Plunker

这显示了基本的想法,但是有一个O(n)解决方案会很好:

angular.module("spells", [])
.controller("spellController", function($scope) {

  $scope.shouldDisable = function(spell) {
    return $scope.numPrepared == $scope.maxPreparedSpells && !spell.isPrepared;
  };

  $scope.spells = [
    {name: "Magic Missile", isPrepared: false},
    {name: "Lightning bolt", isPrepared: false},
    {name: "Cure Major Wounds", isPrepared: false}
  ];

  $scope.maxPreparedSpells = 2;
  $scope.numPrepared = 0;

  $scope.updateNumPreparedSpells = function(spell) {
    if (spell.isPrepared) {
      $scope.numPrepared++;
    }
    else {
      $scope.numPrepared--;
    }
  };
});

诀窍是每次点击一个复选框时都会调用updateNumPreparedSpells

<input type="checkbox" ng-click="updateNumPreparedSpells(spell)" ng-model="spell.isPrepared" ng-disabled="shouldDisable(spell)"/>{{spell.name}}

现在,不需要遍历法术列表来计算准备的数字。当然,这假设每个咒语的准备状态只能通过单击复选框来改变 。如果可以在其他地方更改数据,则计数可能不正确。这种情况与缓存失效问题相当,后者已知很难。