2012-12-18 16 views
55

Irgendwie, durch die Magie von Angular, wenn Sie ng-model verwenden und es einen booleschen Wert zur Verfügung stellen, wird Ihr Kontrollkästchen überprüft, ob der Boolesche Wert wahr ist, und deaktiviert, wenn falsch.AngularJS: Reverse Checkbox Status

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

Während dies allein ziemlich verwirrend ist, ich versuche tatsächlich den geprüfte Zustand rückgängig zu machen, denn im Gegensatz zu dem todo Beispiel, wo todo.done die Box bedeutet, wird überprüft, ist mein Modell mehr wie todo.incomplete.

Leider meine erste Vermutung hat nicht funktioniert:

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

ich in der Lage bin, wo das Modell mir diktiert wurde, so kann ich es nicht haben, ändern und will nicht massage es auf dem Client (weil ich Client-Objekte zurück zum Server sende, da es in einer vertrauenswürdigen Umgebung läuft).

aktualisieren

Dies funktioniert in 1.3 und nicht geben Sie Strings (1.2.xxx gab dir Saiten statt booleans):

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

oder einfach nur eine Negation jeglicher Wort verwenden Sie Ihr Modell beschreiben zu: video.shown:? oder verwenden Sie eine Funktion in Ihrem Controller, um den Wert eines anderen Modells zu setzen, wenn das Kontrollkästchen aktiviert ist ... es ist meiner Meinung nach kein echtes Problem. – mpm

+0

@camus Das letzte, was ich sagte, war, dass ich das Modell nicht ändern wollte, und das sollte ich nicht tun müssen. Natürlich ist es kein wirkliches Problem, aber wenn ein Framework einfach zu bedienen ist, gibt es keinen Grund, warum meine erste Vermutung nicht funktionieren sollte. – Langdon

+1

Die Verwendung einer Funktion ändert nicht das Modell, sondern fügt eine Funktion zu einem Controller hinzu. Und kein Rahmen ist eine Wunderwaffe. Aber dieses ist leicht ausdehnbar, das musst du sowieso machen, Direktiven schreiben. – mpm

Antwort

69

Sie können das jetzt machen, ohne die Notwendigkeit von benutzerdefinierter Richtlinie, Winkel Unterstützung ng-true-value und ng-false-value

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

Ihr Beispiel soll jetzt funktionieren <input type="checkbox" ng-model="video.hidden" ng-true-value="false" ng-false-value="true">

+1

Problem mit dieser Lösung ist, dass das Kontrollkästchen weiterhin den video.hidden-Wert anzeigt, wenn angezeigt wird. –

+0

Sieht so aus, als hätten sie es in 1.3 behoben. – Langdon

+0

Ich sehe 'ng-true-value' und' ng-false-value', aber der 'false' Wert wird nicht an den Server gesendet. Vielleicht wird es als nicht erfolgreiche Formkontrolle behandelt. –

23

Ich glaube nicht, es gibt einen Weg zu tue das rein in der Vorlage. Der naheliegendste Weg, dies zu erreichen, ist das Erstellen einer neuen Bereichsvariablen, die manuell an Ihren Modellwert gebunden wird. So wie:

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

Und in Ihrem Controller:

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

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

Man könnte fast verwenden nur einen Weg, um mit einem ng Wechsel Bindung, aber das funktioniert nicht ganz:

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

Da ng-change den aktuellen Wert überhaupt nicht in den lokalen Bereich mischt. Wenn Sie in einem Kontext waren, in dem Sie Zugriff auf den NgModelController hatten, könnten Sie etwas tun, aber Sie würden dafür eine benutzerdefinierte Anweisung benötigen. Es wäre nicht schwer, eine "invertierte" Attributrichtlinie zu erstellen, die die Formatierer und Parser des NgModel modifiziert. Ich würde vorschlagen, dass wenn Sie viele invertierte Kontrollkästchen benötigen.

bearbeiten

Für die Nachwelt ein „umgekehrtes“ Attribut zu machen ist super einfach, könnte genauso gut, genau das tun. Direktiven zu machen erscheint zunächst immer wie ein Schmerz, aber es ist wirklich der Winkelweg.

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

Könnte die Priorität setzen müssen, oder „unshift“ statt Push, um sicherzustellen, dass diese Jungs laufen nach dem eingebauten in inputDirective diejenigen.

+0

Was ist 'ngModel' Argument hier? Gibt es irgendwelche Unterlagen darüber? oder ist es eine Art von DI-Magie? –

+1

Das vierte Argument zu "link" spiegelt, was immer Sie benötigen. – jpsimons

13

Dies scheint

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

Sie führt eine video.checked Eigenschaft zu arbeiten, die das Gegenteil von video.hidden ist und sobald das Kontrollkästchen Änderungen werden die Werte aktualisiert.

Beispiel hier: http://plnkr.co/edit/7HYht6ubkUUJQ0r3g16m?p=preview

+0

Schön, das scheint zu funktionieren. Ist der 'ng-init' Teil jedoch notwendig? Haben Sie innerhalb von 'ng-change' keinen Zugriff auf die' Eingabe', um den markierten Status zu lesen? – Langdon

+0

ohne 'ng-init' wenn die Ansicht kompiliert wird, wäre der Wert von' video.checked' 'undefiniert' und Checkboxen wären deaktiviert, selbst wenn' video.hidden' auf 'false' gesetzt ist, was dann der Fall ist . Wenn Sie 'ng-init' entfernen, müssen Sie Ihre' videos' Objekte vom Controller modifizieren und von dort aus initialisieren. – jaime

+1

Sie haben also keinen Zugriff auf den Zieleingang innerhalb von ng-change? Wie könnte ich nicht sagen: 'ng-change =" video.hidden =! $ Element.checked "' – Langdon

4

Meine Lösung verwendet eine Richtlinie „negieren“, dass Sie nur an den „Eingang“ hinzufügen. Es ist einfach und es ist nicht notwendig, den Controller zu ändern.

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; 
        }); 
       } 
      }; 
     } 
    ] 
); 

es wie folgt verwendet:

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

Ich denke, die einfachste Lösung, die aktiviert oder deaktiviert Wert für eine Checkbox, indem Sie die ng-init-Richtlinie ist innerhalb der Checkbox Eingabeelement wie folgt zu erhalten:

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

Dieser den Anfangswert der Checkbox ermöglicht, falsch sein, wenn der Status nicht aktiviert ist. Wenn das Kontrollkästchen deaktiviert ist, wird beim Zurücksenden des Formulars der zurückgegebene Wert (oder die Konsole) falsch sein und nicht "undefiniert", andernfalls wird er bei der Überprüfung als wahr erkannt.

wenn Sie nach Maß Werte für den wahren oder falschen Zustand hinzufügen möchten, können Sie verwenden:

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

und

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

innerhalb des Eingabeelement. wie:

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

ist meine Lösung sehr einfach: ng-true-Wert/ng-falsch-Wert und setzte falsch verwenden, um ng-true-Wert und um wahr zu ng-falsch-Wert was die Funktionalität umkehrt.

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

Verwandte Themen