我刚刚开始学习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
设置为true
或false
)。这也很好。
<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
,但我不确定是什么。
答案 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>
这显示了基本的想法,但是有一个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}}
现在,不需要遍历法术列表来计算准备的数字。当然,这假设每个咒语的准备状态只能通过单击复选框来改变 。如果可以在其他地方更改数据,则计数可能不正确。这种情况与缓存失效问题相当,后者已知很难。