2012-05-14 42 views
12

Tôi có một hộp kiểm bị ràng buộc với một quan sát trên một mô hình xem. Tôi có một yêu cầu về cơ bản bật lên một "Bạn có chắc chắn?" lời nhắc xác nhận nếu người dùng thay đổi nó từ true thành false. Tôi đang có một thời gian khủng khiếp để tìm ra nơi tốt nhất để thực hiện thay đổi "có thể hủy". . .Loại bỏ - Hủy sự kiện thay đổi?

1) jQuery handler cho sự kiện nhấp chuột 2) ViewModel nội bộ đăng ký "beforeChange" 3) ViewModel nội bộ đăng ký (bình thường)

Trong mọi trường hợp, tôi đã bao la thích có cơ hội để hủy bỏ thay đổi hoàn toàn hơn là phản ứng với thay đổi, có khả năng hoàn nguyên về giá trị trước đó nếu cần.

Sự kiện đăng ký của Knockout có cho bạn cơ hội hủy thay đổi không? Bất kỳ cái nhìn sâu sắc sẽ được đánh giá cao. Cảm ơn!

Trả lời

22

Dưới đây là một lựa chọn đơn giản sử dụng stopImmediatePropagation jQuery:

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

Ồ, chúa ơi! Điều đó thật tuyệt vời. Tôi chưa bao giờ biết về stopImmediatePropagation của jQuery(). Trong khi tôi thường cố gắng tránh tham chiếu các công cụ jQuery bên ngoài khung nhìn lõiModel, đây là một giải pháp tuyệt vời cho vấn đề của tôi. Cám ơn bạn một lần nữa! – blaster

+2

Trong trường hợp của tôi 'event.stopImmediatePropagation' không ngăn giá trị thay đổi trong ko viewModel. Tôi phải đặt lại giá trị: 'var cb = event.target; ... data.myvalue (! cb.checked); ' – Sprockincat

+10

Thứ tự của liên kết dữ liệu là * rất * quan trọng trong trường hợp này. Nếu bạn liên kết giá trị * trước * sự kiện, giá trị ràng buộc thực hiện trước tiên. Nếu sự kiện bị ràng buộc, nó sẽ thực hiện đầu tiên và dừng quá trình truyền. Xem này fiddle để xem nó bị hỏng: http://jsfiddle.net/8AuVj/ –

12

Bởi vì trong những vấn đề nhận xét trong @RP Niemeyer câu trả lời, tôi vừa thực hiện người mở rộng này:

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

Sau đó bạn có thể áp dụng được cho mô hình của bạn như thế này:

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

Và, nếu có một trường hợp trong đó không yêu cầu xác nhận (trong ví dụ ngớ ngẩn này, chúng tôi sẽ bỏ qua xác nhận trong tháng ba), bạn có thể làm:

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

Tuyệt vời! Nó có thể được sử dụng trong nhiều tình huống. Chỉ cần một điều, nó nên được sử dụng như thế này: '.extend ({confirmable: {message:" Bạn có chắc không? ", Trừ khi: function() {return new Date(). GetMonth() == 2}}}) ; ' – Sljux

+0

Tuyệt vời! Đó là một ý tưởng được thiết kế tuyệt vời. –

Các vấn đề liên quan