2012-06-20 17 views
21

Câu hỏi này tương tự như knockoutjs databind with jquery-ui datepicker, nhưng thay vì trình ghi ngày tháng jQueryUI, tôi muốn sử dụng một trong số Bootstrap datepickers.Trình giữ ngày tháng khởi động với mã dữ liệu knockout.js

API dành cho trình khởi tạo ngày khởi động Bootstrap khác với jquery-ui và tôi gặp một số rắc rối khi gói đầu xung quanh làm cho nó hoạt động với knockout.js. Tôi đã tạo a jsFiddle to try it out.

Có vẻ như bộ đếm ngày của Bootstrap có thể đơn giản hơn nhiều để sử dụng vì nó không lưu trữ ngày tháng độc lập. Tuy nhiên, tôi muốn biết làm thế nào liệu jsFiddle là cách thích hợp để sử dụng widget datepicker Bootstrap với knockout.js tức

ko.bindingHandlers.datepicker = { 
    init: function(element, valueAccessor, allBindingsAccessor) { 
     //initialize datepicker with some optional options 
     var options = allBindingsAccessor().datepickerOptions || {}; 
     $(element).datepicker(options); 

     ko.utils.domNodeDisposal.addDisposeCallback(element, function() { 
      $(element).datepicker("destroy"); 
     }); 
    }, 
    update: function(element, valueAccessor) { 
    } 
}; 

Trả lời

40

Đây là một mẫu về cách bạn có thể thực hiện điều này với datepicker rằng bạn đang sử dụng :

ko.bindingHandlers.datepicker = { 
    init: function(element, valueAccessor, allBindingsAccessor) { 
     //initialize datepicker with some optional options 
     var options = allBindingsAccessor().datepickerOptions || {}; 
     $(element).datepicker(options); 

     //when a user changes the date, update the view model 
     ko.utils.registerEventHandler(element, "changeDate", function(event) { 
      var value = valueAccessor(); 
      if (ko.isObservable(value)) { 
       value(event.date); 
      }     
     }); 
    }, 
    update: function(element, valueAccessor) { 
     var widget = $(element).data("datepicker"); 
     //when the view model is updated, update the widget 
     if (widget) { 
      widget.date = ko.utils.unwrapObservable(valueAccessor()); 
      if (widget.date) { 
       widget.setValue();    
      } 
     } 
    } 
}; 

Có vẻ như không có bất kỳ chức năng phá hủy nào, vì vậy tôi đã xóa phần đó. Thao tác này xử lý các sự kiện changeDate để cập nhật mô hình chế độ xem khi người dùng thay đổi ngày. Các chức năng update xử lý khi mô hình xem được thay đổi để cập nhật các widget.

Nếu bạn muốn ràng buộc giá trị với một không thể quan sát được, thì mã sẽ mất nhiều mã hơn một chút. Hãy cho tôi biết nếu đó là một cái gì đó mà bạn cần phải hỗ trợ.

http://jsfiddle.net/rniemeyer/KLpq7/

+2

Đây là a [jsFiddle] (http://jsfiddle.net/bmh_ca/uQcCx/2/) có chuyển đổi chuỗi ngày tháng> đáng tin cậy hơn khi trường được cập nhật. Điều này vẫn có báo trước rằng chỉ thay đổi thông qua các widget được đăng ký; việc thay đổi trường nhập không cập nhật mô hình. –

+2

Đây là bản cập nhật để ràng buộc với sự kiện 'thay đổi' để phản hồi các thay đổi đối với trường nhập: http://jsfiddle.net/rniemeyer/uQcCx/3/ –

+0

JsFiddles ở trên dường như không hoạt động nữa, bạn có thực hiện một số thay đổi kể từ ?, thử nghiệm chrome và firefox, datepicker không hiển thị nữa. Chúc mừng – dtjmsy

2

Đây là những gì tôi đã kết thúc

ko.bindingHandlers.datepicker = { 
init: function (element, valueAccessor, allBindingsAccessor) { 
    //initialize datepicker with some optional options 

    var options = { 
     autoclose: true, 
     format: 'yyyy-mm-dd', 
    } 

    //var options = allBindingsAccessor().datepickerOptions || {}; 
    $(element).datepicker(options); 

    //when a user changes the date, update the view model 
    ko.utils.registerEventHandler(element, "changeDate", function (event) { 
     var value = valueAccessor(); 

     if (ko.isObservable(value)) { 
      var myDate = event.date; 
      var month = myDate.getMonth() + 1; 
      var monthText = month; 

      if (month < 10) 
       monthText = "0" + month; 

      var day1 = parseInt(myDate.getDate()); 
      var dayText = day1; 

      if (day1 < 10) 
       dayText = '0' + day1; 

      value(myDate.getFullYear() + '-' + monthText + '-' + dayText); 
     } 
    }); 
}, 
update: function (element, valueAccessor) { 

    var widget = $(element).data("datepicker"); 
    //when the view model is updated, update the widget 
    if (widget) { 
     widget.date = ko.utils.unwrapObservable(valueAccessor()); 
     widget.setValue(widget.date); 
    } 
}}; 
5

Câu trả lời được chấp nhận không làm việc cho tôi với phiên bản hiện tại của bộ chọn ngày. Dữ liệu nhập không được khởi tạo với giá trị của quan sát được. Tôi đã thực hiện một ràng buộc cập nhật, mà tôi đã thêm điều này:

$(element).datepicker('update', dataSource()); 

Điều đó dường như làm điều đó.

Dưới đây là một fiddle cập nhật có sử dụng bộ chọn ngày mới nhất có sẵn, Bootstrap, jQuery, và Knockout: http://jsfiddle.net/krainey/nxhqerxg/

Cập nhật:

tôi đã trải qua một số khó khăn với bộ chọn ngày không chơi độc đáo với các quan sát khi người dùng chỉnh sửa giá trị trong trường văn bản theo cách thủ công. Công cụ sẽ ngay lập tức phân tích cú pháp ngày và cắm kết quả vào trường nhập.

Nếu người dùng cố gắng chỉnh sửa 10/07/2014, và sử dụng phím xóa hoặc xóa để xóa số (10/0/2014), giá trị kết quả sẽ được phân tích ngay lập tức và chèn vào nhập văn bản . Nếu giá trị là, trong một khoảnh khắc, ngày 10 tháng 4 năm 2014, công cụ chọn sẽ chuyển lịch sang ngày 30 tháng 9 năm 2014 và cắm giá trị đó vào trường văn bản. Nếu tôi cố gắng chỉnh sửa tháng và giá trị là, trong một thời điểm, 1/7/2014, công cụ chọn sẽ chuyển sang ngày 7 tháng 1 năm 2014 và cắm giá trị đó vào trường văn bản.

Bạn có thể thấy rằng hành vi trong fiddle này:

http://jsfiddle.net/krainey/nxhqerxg/10/

tôi phải cập nhật của tôi ràng buộc với một handler đặc biệt để phát hiện tập trung, và ràng buộc một sự kiện mờ một lần để có được nó để xử lý thủ công chỉnh sửa chính xác.

$(element).on("changeDate", function (ev) { 
    var observable = valueAccessor(); 
    if ($(element).is(':focus')) { 
     // Don't update while the user is in the field... 
     // Instead, handle focus loss 
     $(element).one('blur', function(ev){ 
      var dateVal = $(element).datepicker("getDate"); 
      observable(dateVal); 
     }); 
    } 
    else { 
     observable(ev.date); 
    } 
}); 

Các fiddle tham chiếu trong câu trả lời ban đầu đã được cập nhật để phản ánh điều này:

http://jsfiddle.net/krainey/nxhqerxg/

5

phiên bản hiện tại của tôi là một sự pha trộn giữa các giải pháp đã được chứng minh:

ko.bindingHandlers.datepicker = { 
init: function (element, valueAccessor, allBindingsAccessor) { 

    var unwrap = ko.utils.unwrapObservable; 
    var dataSource = valueAccessor(); 
    var binding = allBindingsAccessor(); 

    //initialize datepicker with some optional options 
    var options = allBindingsAccessor().datepickerOptions || {}; 
    $(element).datepicker(options); 
    $(element).datepicker('update', dataSource()); 
    //when a user changes the date, update the view model 
    ko.utils.registerEventHandler(element, "changeDate", function (event) { 
     var value = valueAccessor(); 
     if (ko.isObservable(value)) { 
      value(event.date); 
     } 
    }); 
}, 
update: function (element, valueAccessor) { 
    var widget = $(element).data("datepicker"); 

    var value = ko.utils.unwrapObservable(valueAccessor()); 

    //when the view model is updated, update the widget 
    if (widget) { 
     widget.date = value; 
     if (widget.date) { 
      widget.setValue(); 
      $(element).datepicker('update', value) 
     } 
    } 
}};