AngularJS - переключатели ng-repeat с отменой выбора / отменой выбора

Я пытаюсь создать блок ng-repeat для переключателей. Мне нужно, чтобы кнопки были отменяемыми.

Вот пример блока ng-repeat:

<div ng-repeat="role in roles" class="checkbox checkbox-inline checkbox-primary">
 <input id="{{ role.Value }}" ng-model="$parent.roleSelected" class="styled" type="radio" 
   name="{{ role.Group }}" value="{{ role.Value }}" />
 <label for="{{ role.Value }}">{{ role.Name }}</label>
</div>

Редактировать: функция использования отменяемого переключателя при нажатии на ту же кнопку была предоставлена ​​клиентом в качестве требования. Этот вопрос о том, как это можно сделать, а не о том, следует ли это делать.

2 ответа

Решение

Я провел поиск и обнаружил, что отмена выбора переключателей не так проста. Ниже приведен вопрос, который несколько его затронул, но, похоже, он не работает, когда выполняется в блоке ng-repeat: AngularJs. Можно ли отменить выбор "радио" ввода HTML нажатием кнопки?

Вот как я решил проблему. Сначала я настраиваю ng-repeat так:

<div ng-repeat="role in roles" class="checkbox checkbox-inline checkbox-primary">
 <input id="{{ role.Value }}" ng-model="$parent.roleSelected" class="styled" type="radio" 
   name="{{ role.Group }}" value="{{ role.Value }}"  ng-click="clickRole($event)" />
 <label for="{{ role.Value }}">{{ role.Name }}</label>
</div>

В контроллере у меня есть два метода. Один для ng-click и тот, который следит за изменениями в ng-модели. У меня также есть массив ($scope.rolesSelected), который отслеживает выбранные роли. (У меня было несколько блоков ng-repeat на странице, некоторые были радио, некоторые были флажками).

Когда радио (или флажок) щелкается, оно выполняет функцию clickRole(), которая добавляет roleSelected к массиву roleSelected.

$scope.clickRole = function (event) {
    if (event.target.type != 'radio') { // for checkboxes
        addOrRemoveFromArray($scope.rolesSelected, event.target.value);
    } else { // for radio - uncheck radio if selection was removed
        var addedRole = addOrRemoveFromArray($scope.rolesSelected, event.target.value);
        if (!addedRole) {
            event.target.checked = false;
        }
    }
}

Функция addOrRemoveFromArray() просто добавляет данное значение, если его еще нет в массиве, в противном случае удаляет его. Это позволяет удалить выбранную роль, когда переключатель дважды щелкнул (один раз, чтобы добавить, второй, чтобы удалить его).

function addOrRemoveFromArray(array, value) {
    if (typeof value == 'undefined') { return; }
    var index = array.indexOf(value);
    if (index > -1) {
        array.splice(index, 1);
        return false;
    } else {
        array.push(value);
        return true;
    }
}

Вплоть до этого он обрабатывает добавление роли и удаление роли, если отменить выбор. (также обрабатывает добавить / удалить для флажков). Но для радио, при выборе другой роли, она не удаляет предыдущую. Так что нужна еще одна функция watch() для этого на ng-модели.

$scope.$watch('roleSelected', function (newValue, oldValue) {  
  removeFromArray($scope.rolesSelected, oldValue); 
});

Наконец, благодаря этому я смог справиться со сменой ролей на переключателях и отменой выбора.

Это заняло у меня много времени, чтобы разобраться, поэтому я публикую здесь сообщения на случай, если кто-нибудь еще столкнется с подобной ситуацией. Спасибо!

А как насчет использования флажка, а только с одним выбираемым элементом?

<div ng-repeat="role in roles" class="checkbox checkbox-inline checkbox-primary">
       <input id="{{ role.Value }}" ng-click="setRole(role.Value)" ng-checked="role.Value == roleSelected" class="styled" type="checkbox"
          name="{{ role.Group }}" value="{{ role.Value }}" />
       <label for="{{ role.Value }}">{{ role.Name }}</label>
</div>

И код контроллера:

$scope.setRole = function(value)
{
  if ($scope.roleSelected != value) {
    $scope.roleSelected = value;
  }
  else {
    $scope.roleSelected = null;
  }
}

Демо - версия:

https://plnkr.co/edit/0ZhczYNp9mRPSHl6tOxS?p=preview

Другие вопросы по тегам