2013-12-17 10 views
5

Verwenden von Angular 1.0.7:

Ich habe eine Direktive, die ein gestyltes Kontrollkästchen anzeigen soll.

See plunkr here.

Manchmal (und nicht immer) Update mein Wächter doesnt eine der Variablen siehe meines -umfang:

Hier ist eine versagende Sequenz:

  • foo
  • bar
  • alle
  • foo
  • bar

enter image description here

Ich frage mich, warum das Update leider nicht auftreten.

+0

ich bin nicht sicher, ob ich deinem Problem folge? alles funktioniert für mich, wenn ich auf foo, bar jedes Mal kein Fehler ... –

+0

das ist, wo die *** manchmal *** macht die Dinge schwierig, lass mich versuchen, eine fehlerhafte Sequenz zu finden – apneadiving

+0

bekam eine, in Frage – apneadiving

Antwort

2

Es war sehr interessante Frage, so Problem mit Kombination Ihrer geklickt Handler und Vorlieben.E-Mail Uhr:

AngularJS Code:

//https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js line 4510 
scope.$watch(function parentValueWatch() { 
    var parentValue = parentGet(parentScope); 

    if (parentValue !== scope[scopeName]) { 
     // we are out of sync and need to copy 
     if (parentValue !== lastValue) { 
      // parent changed and it has precedence 
      lastValue = scope[scopeName] = parentValue; 
     } else { 
      // if the parent can be assigned then do so 
      parentSet(parentScope, parentValue = lastValue = scope[scopeName]); 
     } 
    } 
    return parentValue; 
}); 
break; 

Sie starten mit Klick auf foo + bar und wir haben:

all: true 
foo: true 
bar: true 

Klicken Sie durch Toggle alle:

//by this code 
var new_val = toggled_input_value(); 
$scope.model = new_val; 

$ scope.model ist Umfang [Bereichsname] aus dem obigen Code, so Umfang [Bereichsname] = false und Lastvalue = true, parentValue = true (sie wird sich ändern, nachdem Lauf verdauen $)

$scope.clicked({ value: new_val }); 

wird rufen

$scope.toggleAll = function(new_value){ 
    if (new_value){ 
    $scope.preferences.email.foo = true; 
    $scope.preferences.email.bar = true; 
    } 
    else{ 
    $scope.preferences.email.foo = false; 
    $scope.preferences.email.bar = false;  
    } 
} 

so,

all: true - $digest have not been run 
foo: false 
bar: false 

und beginnen $ verdauen ... erste Anruf wird:

$scope.$watch('preferences.email', function(new_value){ 
    var bool = new_value.foo && new_value.bar; 
    $scope.preferences.all = bool; 
}, true); 

so,

all: false 
foo: false 
bar: false 

es ist ein Problem, denn auf der nächsten parentValueWatch Anruf werden wir bekommen:

parentValue = false //$scope.preferences.all 
scope[scopeName] = false //$scope.model 
lastValue = true 

so, parentValue === Umfang [Bereichsname] und lastValue wurden nicht aktualisiert ... es ist ein Fehler :)

wenn Sie chang e $ scope.preferences.all zum wahren, werden Sie

$scope.preferences.all === lastValue //true 

bekommen und

// if the parent can be assigned then do so 
parentSet(parentScope, parentValue = lastValue = scope[scopeName]); 

so, $ scope.preferences.all falsch wird sich nennen, statt eine echte

du kannst dir das hier ansehen http://plnkr.co/edit/YEHqA101YwWKDvK6odFf?p=preview (console.trace)

+0

das ist eine gute Antwort ... – apneadiving

+0

ok so ist es ein eckiger Bug? – apneadiving

+0

mein Problem ist, dass, wenn ich den Rückruf verwende, der Controller immer noch ein nicht aktualisiertes Objekt trägt. Deshalb habe ich $ watch benutzt, was anscheinend auch keine gute Idee ist :) – apneadiving

2

Es gibt eine Menge Code, den Sie nicht brauchen. Ein Teil dieses Codes, der nicht genau sicher ist, welche Zeile, stört. Hauptsächlich müssen Sie das Modell nicht manuell auf das Kontrollkästchen setzen, wenn Sie in Ihrer Vorlage ng-model='model' setzen, ist das alles, was Sie brauchen!

Also hier ist die funktionierende gegabelte Version Ihres Codes, die funktioniert: http://plnkr.co/edit/CzhiAVEAuDtiL2QO95Za und wie Sie sehen können, entfernte ich fast alles, was Sie in Bezug auf das Modell getan haben, da es alles automatisch ist.

Fassen wir zusammen, was wir taten:

  1. entfernt, um die Pre-Compile-Code, es sei denn, Sie Namen müssen vor kompilieren zu definieren? nicht sicher warum.
  2. keine Notwendigkeit für Eingabewertfunktionen, es ist wahr oder falsch oder? Das geschieht automatisch durch das Modell.
  3. $ scope.select sollte nur den Modellwert umschalten, alles andere ist automatisch.
  4. init-Funktion entfernt Modellwert automatisch ohnehin
  5. die aus dem Inneren der Richtlinie tief Uhr entfernt gesetzt ist, müssen Sie nicht DEEP Uhr hier, wie Sie es die niedrigsten Werte sind vorbei und es ist nicht besorgt über andere Werte. Die äußere Toggle-Funktion ist die einzige Sache, die um das tiefe Beobachten besorgt ist.

Vereinfachte Richtlinie Code:

app.directive("uuCheckbox", function() { 
return { 
    restrict: "A", 
    transclude: true, 
    scope: { 
    model: '=', 
    clicked: '&' 
    }, 
    template: "<div ng-click='select()'>" + 
    "<span ng-class='{ checked: model }'></span>" + 
    "<input class='hidden' value='true' type='checkbox' ng-model='model'>" + 
    "<span ng-class='{red: model}' ng-transclude></span>" + 
    "</div>", 
    compile: function(elmt, tAttrs) { 
    return function($scope, element, attrs) { 
     element.find('input').attr('name', attrs.name); 
     var on_change = function(new_value) { 
     $scope.clicked({ value: new_value }); 
     }; 
     $scope.$watch('model', on_change); 
     $scope.select = function() { 
     $scope.model = !$scope.model; 
     }; 
    }; 
    } 
}; 
}); 
+0

Ich brauche die Vorkompilierung, da das Kontrollkästchen aktiviert sein muss, wenn die html -Eigenschaft aktiviert ist, das ist eine der Optionen, die ich auf die gleiche Weise wie der Name (aber in meinem Beispiel entfernt, um minimalen Code angezeigt) – apneadiving

+0

und ein Kontrollkästchen ist nicht einfach true/false, kann irgendeinen Wert oder false haben (also ja, ich muss den Wert bekommen, den ich in args übergebe) – apneadiving

+0

frage mich, wie man den richtigen Wert an das Modell weitergibt, ohne den Eingabewert – apneadiving

Verwandte Themen