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>

Изменить. Возможность использования переключателя, который можно отменить, нажав ту же кнопку, была предоставлена ​​заказчиком в качестве требования. Это вопрос о том, как это можно сделать, а не о том, следует ли это делать.


person John Lee    schedule 13.02.2016    source источник
comment
отключается как? Через кнопку?   -  person Johannes Jander    schedule 14.02.2016
comment
нет, выбор можно отменить, нажав ту же кнопку-переключатель еще раз. Как флажок. Я разместил свой ответ ниже. Благодарность!   -  person John Lee    schedule 14.02.2016
comment
Не делай этого. Люди ожидают, что радиокнопки будут работать по-другому. Это просто дает вашим пользователям действительно плохой пользовательский опыт.   -  person Johannes Jander    schedule 14.02.2016
comment
Я согласен, но это стало требованием. Пользователь нуждался в радио, чтобы разрешить только один выбор. Однако, если это было сделано случайно, они хотели отменить выбор, например, флажок. И они хотели, чтобы это выглядело как флажок, который вы можете видеть в моих определениях классов css...   -  person John Lee    schedule 14.02.2016


Ответы (2)


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

<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

person Robin Thoni    schedule 13.02.2016

Я немного поискал и обнаружил, что отменить выбор переключателей не так просто. Ниже приведен вопрос, который несколько касался его, но, похоже, он не работает, когда выполняется в блоке 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 в массив rolesSelected.

$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;
    }
}

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

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

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

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

person John Lee    schedule 13.02.2016