2012-12-18 19 views
55

Jakoś, dzięki magii Angular, jeśli użyjesz ng-model i zapewnisz mu wartość boolowską, pole wyboru zostanie sprawdzone, jeśli wspomniana wartość logiczna jest prawdziwa, i odznaczona, jeśli jest fałszywa.AngularJS: Reverse checkbox State

<input type="checkbox" ng-model="video.hidden"> 

Choć sam jest dość kłopotliwe, ja rzeczywiście próbuje odwrócić sprawdzenie stanu, ponieważ w przeciwieństwie do np todo gdzie todo.done oznacza pole zostanie zaznaczone, mój model jest bardziej jak todo.incomplete.

Niestety moje pierwsze przypuszczenie nie działa:

<input type="checkbox" ng-model="!video.hidden"> 

jestem w sytuacji, w której model został dyktowane do mnie, więc nie można go zmienić i nie chcą mieć do masuj go na kliencie (ponieważ wysyłam obiekty klienta z powrotem na serwer, ponieważ działa on w zaufanym środowisku).

Aktualizacja

To działa w 1.3 i nie daje ciągi (1.2.xxx dał ci struny zamiast logicznych):

<input type="checkbox" ng-model="video.hidden" ng-true-value="false" ng-false-value="true"> 
+0

lub po prostu użyć negację jakiegokolwiek słowem używanym do opisania modelu video.shown? lub użyj funkcji w kontrolerze, aby ustawić wartość innego modelu, gdy pole wyboru jest zaznaczone ... to nie jest prawdziwy problem w mojej opinii. – mpm

+0

@camus Ostatnią rzeczą, którą powiedziałem, było to, że nie chciałem zmienić modelu i nie powinienem był tego robić. Oczywiście nie jest to prawdziwy problem, ale kiedy ramy są zachwalające łatwość użycia, nie ma powodu, dla którego moje pierwsze przypuszczenie powyżej nie powinno działać. – Langdon

+1

użycie funkcji nie powoduje zmiany modelu, ale dodanie funkcji do kontrolera. Żadna struktura nie jest srebrną kulą. Ale ta jest łatwa do rozłożenia, to i tak musisz zrobić, pisz dyrektywy. – mpm

Odpowiedz

69

Można zrobić to teraz bez potrzeby Dyrektywy niestandardowego, kanciasty wsparcia ng-true-value i ng-false-value

https://docs.angularjs.org/api/ng/input/input[checkbox]

Twój przykład powinien działać teraz <input type="checkbox" ng-model="video.hidden" ng-true-value="false" ng-false-value="true">

+1

Problem z tym rozwiązaniem polega na tym, że pole wyboru nadal będzie wyświetlało wartość wideo.hidden podczas wyświetlania. –

+0

Wygląda na to, że naprawili go w wersji 1.3. – Langdon

+0

Widzę 'ng-true-value' oraz' ng-false-value', ale wartość 'false' nie jest wysyłana do serwera. Może to traktowane jako nieskuteczna kontrola form. –

23

nie sądzę, istnieje sposób, aby rób to czysto w szablonie. Najbardziej oczywistym sposobem osiągnięcia tego jest utworzenie nowej zmiennej zasięgu, która jest ręcznie podwójnie związana z wartością twojego modelu. Więc tak:

<input type="checkbox" ng-model="videoShowing"> 

A w kontrolerze:

$scope.videoShowing = !$scope.video.hidden; 

$scope.$watch('video.hidden', function(value) { 
    $scope.videoShowing = !value; 
}); 
$scope.$watch('videoShowing', function(value) { 
    $scope.video.hidden = !value; 
} 

Można prawie prostu używać wiązania z NG-zmiany w jedną stronę, ale to nie do końca pracy:

<input type="checkbox" ng-checked="!video.hidden" ng-change="???"> 

Ponieważ ng-change w ogóle nie miesza aktualnej wartości do zakresu lokalnego. Jeśli byłeś w sytuacji, w której miałeś dostęp do NgModelController, mógłbyś coś zrobić, ale potrzebujesz do tego niestandardowej dyrektywy. Nie byłoby trudno stworzyć "odwróconą" dyrektywę atrybutów, która modyfikuje formatery i parsery NgModel. Zasugeruję, że jeśli potrzebujesz dużo odwróconych pól wyboru.

Edit

dla potomności, dokonywania "odwróconego" atrybut jest super prosty, równie dobrze może to zrobić. Wytwarzanie dyrektyw zawsze wydaje się być początkiem bólu, ale tak naprawdę jest to metoda Angular.

someModule.directive('inverted', function() { 
    return { 
    require: 'ngModel', 
    link: function(scope, element, attrs, ngModel) { 
     ngModel.$parsers.push(function(val) { return !val; }); 
     ngModel.$formatters.push(function(val) { return !val; }); 
    } 
    }; 
}); 

może trzeba ustawić priorytet też, czy „unshift” zamiast push, aby upewnić się, że ci faceci są prowadzone po wbudowanej te inputDirective.

+0

co to jest tutaj argument 'ngModel'? czy jest na to jakaś dokumentacja? czy jest to jakiś rodzaj magii DI? –

+1

Czwarty argument do "link" odzwierciedla to, czego "potrzebujesz". – jpsimons

13

To wydaje się działać

<input type="checkbox" 
     ng-init = "video.checked = !video.hidden" 
     ng-model ="video.checked" 
     ng-change ="video.hidden = !video.checked"/> 

Wprowadza video.checked właściwość, która jest przeciwieństwem video.hidden i tak szybko, jak zmienia się pole wyboru wartości są aktualizowane.

Przykład tutaj: http://plnkr.co/edit/7HYht6ubkUUJQ0r3g16m?p=preview

+0

Dobrze, wygląda na to, że działa. Czy jednak część 'ng-init' jest konieczna? Wewnątrz 'ng-change', czy nie masz dostępu do' input' odczytywanego z niego stanu sprawdzonego? – Langdon

+0

bez 'ng-init' podczas kompilacji widoku wartość' video.checked' byłaby 'niezdefiniowana', a checkboxy nie były zaznaczone, nawet jeśli' video.hidden' jest ustawione na 'false', co jest gdy chcesz je sprawdzić . Jeśli usuniesz 'ng-init', będziesz musiał zmodyfikować obiekty' videos' ze sterownika i wykonać inicjalizację stamtąd. – jaime

+1

Więc nie masz dostępu do docelowego 'input' wewnątrz Ng-Change? Nie mogłem powiedzieć: 'ng-change =" video.hidden =! $ Element.checked "' – Langdon

4

Moje rozwiązanie używa dyrektywą „negować”, które po prostu dodać do „wejścia”. To proste i nie ma potrzeby zmiany kontrolera.

angular 
    .module("<< your module >>") 
    .directive('negate', [ 
     function() { 
      return { 
       require: 'ngModel', 
       link: function (scope, element, attribute, ngModelController) { 
        ngModelController.$isEmpty = function(value) { 
         return !!value; 
        }; 

        ngModelController.$formatters.unshift(function (value) { 
         return !value; 
        }); 

        ngModelController.$parsers.unshift(function (value) { 
         return !value; 
        }); 
       } 
      }; 
     } 
    ] 
); 

Używaj go tak:

<input type="checkbox" negate ng-model="entity.nologin"> 
0

Myślę, że najprostsze rozwiązanie, aby uzyskać zaznaczone lub odznaczone wartość do wyboru jest dodanie dyrektywy ng-startowy wewnątrz elementu wejściowego pole wyboru w następujący sposób:

<input type="checkbox" ng-init="video = false" ng-model="video" > 

Umożliwia to wartość początkową pole wyboru być fałszywe, gdyby państwo nie zostało sprawdzone. Po przesłaniu formularza, jeśli pole wyboru nie jest zaznaczone, wartość, która zwraca (lub konsola) będzie fałszywa, zamiast "niezdefiniowana", w przeciwnym razie sprawdzenie będzie prawdą.

jeśli chcesz dodać niestandardowy dokonane wartości prawdziwej lub fałszywej stanie, można użyć:

ng-true-value="'custom_true value'" 

i

ng-false-value="'custom_false value'" 

wewnątrz elementu wejściowego. jak:

<input type="checkbox" ng-init="video = false" ng-model="video" ng-true-value="'custom_true value'" ng-false-value="'custom_false value'"> 
0

Moje rozwiązanie jest bardzo proste: wystarczy użyć NG-prawdziwa wartość/NG-fałszywie wartość i ustawić fałszywe NG-prawdziwą wartość i prawdziwe ng-fałsz wartość który odwróci funkcjonalność.

<input type="checkbox" ng-model="<<-- Your Model -->> " ng-true-value="false" 
 
      ng-false-value="true">