禁止取消选中 angularJS 中的所有复选框

Disallow unchecking of all checkboxes in angularJS

我对复选框列表使用 AngularJS 指令 checklist-model 但我需要始终至少选中一个复选框。 我通过添加 if:

更改了 checklist-model.js
watch if(current.length > 1)

取消支票前:

scope.$watch(attrs.ngModel, function(newValue, oldValue) {
  if (newValue === oldValue) { 
    return;
  } 
  var current = getter(scope.$parent);
  if (angular.isFunction(setter)) {
    if (newValue === true) {
      setter(scope.$parent, add(current, value, comparator));
    } else {
        if(current.length > 1)
        {
            setter(scope.$parent, remove(current, value, comparator));
        }
    }
  }

  if (checklistChange) {
    checklistChange(scope);
  }
});

问题是UI已经变成unchecked,而model没变

任何人都有关于如何将复选框更改回 "checked" 状态的优雅建议(最好没有 JQuery),或者更好地在它更改为选中之前抓住它?

JSfiddle here,尝试取消选中所有复选框并查看当复选框全部取消选中时(我试图阻止的)模型保持不为空(这很好但还不够)

这可能来自 angular 的异步特性和您正在使用的库。到目前为止我能找到的是像这样的一些肮脏的解决方法(jsfiddle):创建一个事件来跟踪输入的点击并执行以下操作:

  $scope.onclick = function(evt) {
    if ($scope.user.roles.length === 1 && prevLength === 1) {
      evt.preventDefault();
    }

    prevLength = $scope.user.roles.length;
  };

然后将其添加到您的元素中

 ng-click="onclick($event)"

我不是说它很完美,但它确实有效

我的一位同事建议在它是唯一选中的复选框时禁用它,这样你既可以防止更改模块(因此指令甚至不需要更改)并且用户体验更好知道他不能取消选中:

     <input type="checkbox" checklist-model="user.roles" checklist-value="role.id" ng-disabled="shouldDisable(role.id)"> {{role.text}}

 $scope.shouldDisable = function(roleId) {
        var isDisabled = false;
        if($scope.user.roles.length === 1) {
            isDisabled = $scope.user.roles.indexOf(roleId) !== -1;
        }
        return isDisabled;
    }

this JSfiddle

中查看答案

目前组件不支持这个,但是有讨论实现 minlength/maxlength https://github.com/vitalets/checklist-model/issues/15 然后就可以用 checklist-minlength=1.[=13 简单实现了=]

我还编辑了您的实施提案 checklistBeforeChange。我也会在下一批中尝试处理这个问题。在 v0.8.0 中实现。

@ozba 使用 array.some 函数回答的更好版本:

public atLeastOneRowEnabled(row): boolean {
        //at least one row is visible except the current line
        return !this.rows.some(rowIterator => rowIterator.logical_name !== row.logical_name && rowIterator.isVisible);
    }