2012-05-14 14 views
12

Mam pole wyboru powiązane z obserwowalnym w modelu widoku. Mam wymóg, aby w zasadzie wyskoczyć "Czy jesteś pewien?" potwierdzenie, jeśli użytkownik zmieni wartość z "prawda" na "fałsz". Trochę strasznie się zastanawiam, jakie jest najlepsze miejsce, aby zmiana była "możliwa do anulowania". . .Knockout - anulować zmianę zdarzenia?

1) Ładowarka dla jQuery kliknij zdarzenie 2) ViewModel wewnętrzny subscribe "beforeChange" 3) ViewModel wewnętrzny subskrybować (normalny)

W każdym razie, ja ogromnie wolą mieć szansę, aby anulować zmianę od razu reagować na zmianę, potencjalnie powracając do poprzedniej wartości, jeśli zajdzie taka potrzeba.

Czy wydarzenie subskrypcji Knockout daje możliwość anulowania zmiany? Każdy wgląd byłby doceniony. Dzięki!

Odpowiedz

22

Oto prosty opcja jQuery za stopImmediatePropagation:

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

Och, mój Boże! To jest fantastycznie pomocne. Nigdy nie wiedziałem o stopImmediatePropagation() jQuery. Chociaż zwykle staram się unikać odwoływania się do rzeczy jQuery poza core viewModel, jest to świetne rozwiązanie dla mojego problemu. Jeszcze raz dziękuję! – blaster

+2

W moim przypadku 'event.stopImmediatePropagation' nie zatrzymało zmiany wartości w ko viewModel. Musiałem ponownie ustawić wartość: 'var cb = event.target; ... data.myvalue (! cb.checked); ' – Sprockincat

+10

Kolejność powiązania danych jest * bardzo * ważna w tym przypadku. Jeśli wiążemy wartość * przed * zdarzeniem, powiązanie wartości zostanie wykonane jako pierwsze. Jeśli zdarzenie jest powiązane, zostanie wykonane jako pierwsze i zatrzymane zostanie propagowanie. Zobacz to skrzypce, aby je zepsuć: http://jsfiddle.net/8AuVj/ –

12

powodu problemów komentowanych w @RP Niemeyer odpowiedź, właśnie realizowany to rozszerzenie:

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

Można wtedy zastosować że do modelu tak:

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

A jeśli nie był to przypadek, w którym nie prosić o potwierdzenie (w tym głupim przykładzie będziemy pomijać potwierdzenie w marcu), możesz zrobić:

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

Wspaniale! Może być stosowany w wielu scenariuszach. Tylko jedna rzecz, powinna być używana w następujący sposób: '.extend ({confirmable: {message:" Czy jesteś pewien? ", Chyba że: function() {return new Date(). GetMonth() == 2}}}) ; ' – Sljux

+0

Nice! To wspaniale zaprojektowany pomysł. –