2014-04-24 11 views
13

Próbuję zmusić jednokrotnego wyboru na pól, podobny do html „wybierz”angularjs: single Wybierz między wieloma wyboru

Mam HTML prostą tabelę:

<tr ng-repeat="subscription in entities"> 
    <td> 
     <input type="checkbox" ng-checked="isChecked(subscription)" ng-click="toggleSelection(subscription)"/> 
    </td> 
</tr> 

Wtedy mam Niektóre proste funkcje kontrolera dla tych dyrektyw powyżej:

$scope.isChecked = function(entity) { 
    return $scope.checkedEntity === entity; 
}; 

$scope.toggleSelection = function(entity) { 
    entity.checked = !entity.checked; 
    if (entity.checked) { 
     $scope.checkedEntity = entity; 
    } else { 
     $scope.checkedEntity = null; 
    } 
}; 

Niestety to nie działa, i myślę, że właśnie odkrył, dlaczego .... nG-click ma 0 priorytet vs 100 na ng sprawdzane.

Czy istnieje eleganckie rozwiązanie tego problemu?

+0

można udostępnić swoją '$ scope' obiektów –

+0

przykro mi, nie rozumiem co masz na myśli? – Brian

Odpowiedz

21

Bind ng-model do subscription.checked i mają ng-click odznacz wszystkie subskrypcje z wyjątkiem jednego kliknięty. Ponieważ są to pola wyboru, jedno kliknięcie przełącza się.

<tr ng-repeat="subscription in entities"> 
    <td> 
    <input ng-model="subscription.checked" ng-click="updateSelection($index, entities)" type="checkbox" /> 
    </td> 
</tr> 

Można użyć zwykłego for pętlę, ale angular's forEach pozwala nam aliasu każdą pozycję jako subscription i poprawić czytelność:

$scope.updateSelection = function(position, entities) { 
    angular.forEach(entities, function(subscription, index) { 
    if (position != index) 
     subscription.checked = false; 
    }); 
} 

Oto demo pracy: http://plnkr.co/edit/XD7r6PoTWpI4cBjdIZtv?p=preview

+0

Awesome, wielkie dzięki! Interesujące, początkowo wypróbowałem małą odmianę tego, w której przechodzę tylko bieżącą encję na ng-click, a funkcja iteruje nad $ scope.entities, które powinny być tą samą strukturą danych ... ale z jakiegoś powodu twoja działa i moja nie robi! – Brian

+0

Ta składnia jest ładniejsza: P 'entity.map ((x, i) => x.checked = position === i);' – Kutyel

+0

Świetna pomoc Dzięki, dużo! –

0

Zasugeruj jedną z trzech opcji dla ciebie.

  1. Napisz dyrektywę, która ustawi pola wyboru i zarządzi stanem w nich. To nie jest idealne, ponieważ zmieniasz regułę dotyczącą swojego modelu (tylko jedna subskrypcja powinna być sprawdzona) w problemie manipulacji DOM.
  2. Struktura modelu tak, aby tylko jedna subskrypcja była zawsze oznaczona jako aktywna. Jest to trudne, ponieważ modyfikacja modelu przy zmianie spowoduje rozpoczęcie kolejnego cyklu skracania, a nie tego, co chcesz.
  3. Użyj przycisków opcji zamiast pól wyboru. To dostarczy ci modalności, którą chcesz. :-P

Wybrałbym opcję 3 - zawsze jestem fanem czerpania korzyści z natywnych elementów wejściowych.

<tr ng-repeat="subscription in entities"> 
<td><input type="radio" 
    ng-model="selection" 
    name="subscriptionRadio" 
    value="{{subscription}}"/> 
</td> 
</tr> 
+1

Za 1) uzgodniony, nieprzyjemny. Dla 3) Dobrze! Miałem spory spór z projektantem UX o standardach UI, datowanych nie tylko na lata, ale i na dekadę, ale niestety MUSZĄ być to pola wyboru ... * drżenie pięści * Dla nr 2 próbowałem oryginalnie z modelem ng związanym z subskrypcja, a następnie zmieniona na Ng, która następnie zaktualizowałaby model we wszystkich subskrypcjach.Ale w tym przypadku model został zaktualizowany, ale stan "sprawdzony" się nie zmienił, chyba że użyłem jquery, ale staram się tego uniknąć. – Brian

+0

To, co możesz zrobić, to ustawić dyrektywę tak, aby wyzwalała zmianę modelu i rekonfigurowała pola wyboru. wiązanie "dwukierunkowe" jest zdecydowanie rzeczą w dyrektywach Angular i może ci w tym pomóc. –

+1

Sądziłem też, że skorzystałbyś z przycisków radiowych, gdybyś mógł. ;) –

7

<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script> 
 
    <script> 
 
    angular.module('app', []).controller('appc', ['$scope', 
 
     function($scope) { 
 
     $scope.selected = 'other'; 
 
     } 
 
    ]); 
 
    </script> 
 
</head> 
 

 
<body ng-app="app" ng-controller="appc"> 
 
    <label>SELECTED: {{selected}}</label> 
 
    <div> 
 
    <input type="checkbox" ng-checked="selected=='male'" ng-true-value="'male'" ng-model="selected">Male 
 
    <br> 
 
    <input type="checkbox" ng-checked="selected=='female'" ng-true-value="'female'" ng-model="selected">Female 
 
    <br> 
 
    <input type="checkbox" ng-checked="selected=='other'" ng-true-value="'other'" ng-model="selected">Other 
 
    </div> 
 

 

 

 
</body> 
 

 
</html>

0

Użyłem poniższego kodu, aby osiągnąć podobną funkcjonalność. Sztuczka polega na użyciu ng-click, która może dać to całkiem ładnie. checkbox-1 & checkbox-2 mają charakter boolowski.

<form> 
    <input type="checkbox" ng-click="checkbox-2 = false" ng-model="checkbox-1" > 
    <input type="checkbox" ng-click="checkbox-1 = false" ng-model="checkbox-2" > 
</form> 
Powiązane problemy