2012-05-14 6 views
12

Ich habe ein Kontrollkästchen an eine Observable in einem Ansichtsmodell gebunden. Ich habe die Anforderung, ein "Bist du sicher?" Bestätigungsaufforderung, wenn der Benutzer es von wahr zu falsch ändert. Ich habe eine schreckliche Zeit herauszufinden, der beste Ort, um die Änderung "stornierbar" zu machen. . .Knockout - Abbrechen eines Änderungsereignisses?

1) jQuery-Handler für Click-Ereignis 2) Ansichtsmodell interne subscribe "beforeChange" 3) Ansichtsmodell interne abonnieren (normal)

Auf jeden Fall hatte ich wesentlich lieber die Chance haben, um die Änderung abzubrechen direkt als Reaktion auf die Änderung, möglicherweise zurück zu seinem vorherigen Wert, wenn es sein muss.

Bietet Knockouts Abonnement-Event Ihnen die Möglichkeit, eine Änderung zu stornieren? Jeder Einblick würde geschätzt werden. Vielen Dank!

Antwort

22

Hier ist eine einfache Möglichkeit, mit jQuery stopImmediatePropagation ist:

http://jsfiddle.net/rniemeyer/cBvXM/

<input type="checkbox" data-bind="click: confirmCheck, checked: myvalue" /> 

js:

var viewModel = { 
    myvalue: ko.observable(false), 
    confirmCheck: function(data, event) { 
     if (!confirm("Are you sure?")) { 
      event.stopImmediatePropagation();    
      return false; 
     } 
     return true; 
    } 
}; 
+0

Oh mein Gott! Das ist fantastisch hilfreich. Ich wusste nie über jQuery's stopImmediatePropagation(). Während ich normalerweise versuche, jQuery-Sachen außerhalb des Core ViewModel zu referenzieren, ist dies eine großartige Lösung für mein Problem. Danke nochmal! – blaster

+2

In meinem Fall hat 'event.stopImmediatePropagation' den Wert nicht im ko viewModel geändert. Ich musste den Wert erneut setzen: 'var cb = event.target; ... data.myvalue (! cb.checked); ' – Sprockincat

+10

Die Reihenfolge der Datenbindung ist in diesem Fall * sehr * wichtig. Wenn Sie den Wert * vor * das Ereignis binden, wird zuerst die Wertbindung ausgeführt. Wenn das Ereignis gebunden ist, wird es zuerst ausgeführt und die Weitergabe gestoppt. Sieh dir diese Geige an, um sie kaputt zu sehen: http://jsfiddle.net/8AuVj/ –

12

Aufgrund der in @RP Niemeyer Antwort kommentiert Probleme, ich habe gerade umgesetzt dieser Extender:

ko.extenders.confirmable = function(target, options) { 
    var message = options.message; 
    var unless = options.unless || function() { return false; } 
    //create a writeable computed observable to intercept writes to our observable 
    var result = ko.computed({ 
     read: target, //always return the original observables value 
     write: function(newValue) { 
      var current = target(); 

      //ask for confirmation unless you don't have 
      if (unless() || confirm(message)) { 
       target(newValue); 
      } else { 
       target.notifySubscribers(current); 
      } 
     } 
    }).extend({ notify: 'always' }); 

    //return the new computed observable 
    return result; 
}; 

Anschließend können Sie das wie folgt auf Ihr Modell anwenden:

var viewModel = { 
    myvalue: ko.observable(false).extend({confirmable: "Are you sure?"}); 
} 

Und wenn es ein Fall ist, in dem keine Bestätigung fragen (in diesem dummen Beispiel werden wir eine Bestätigung im März überspringen), Sie können tun:

var viewModel = { 
    myvalue: ko.observable(false).extend({confirmable: { message: "Are you sure?", unless: function() { return new Date().getMonth() == 2 }} }); 
} 
+1

Großartig! Es kann in vielen Szenarien verwendet werden. Nur eine Sache sollte so verwendet werden: '.extend ({confirmable: {Nachricht:" Sind Sie sicher? ", Außer: function() {return new Date(). GetMonth() == 2}}} ; ' – Sljux

+0

Schön! Das ist eine großartig konstruierte Idee. –

Verwandte Themen