bootstrap datepicker download
Bootstrap datepicker con knockout.js databind (4)
Esta pregunta es similar al enlace de datos knockoutjs con jquery-ui datepicker , pero en lugar del jQueryUI datepicker, me gustaría usar uno de los datapickers de Bootstrap .
La API para el marcador de fecha Bootstrap es diferente de jquery-ui, y estoy teniendo problemas para hacer que funcione con knockout.js. He creado un jsFiddle para probarlo .
Parece que el datepicker de Bootstrap podría ser mucho más simple de usar porque no almacena la fecha de forma independiente. Sin embargo, me gustaría saber si el jsFiddle es la forma adecuada de usar el widget Bootstrap datepicker con knockout.js, es decir,
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) {
}
};
Aquí es lo que terminé
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);
}
}};
Aquí hay una muestra de cómo puede lograr esto con el selector de fecha que está usando:
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();
}
}
}
};
No parecía que hubiera ninguna funcionalidad de destrucción, así que eliminé esa pieza. Esto maneja el evento widgets changeDate
para actualizar el modelo de vista, cuando un usuario cambia la fecha. La función de update
maneja cuando se cambia el modelo de vista para actualizar el widget.
Si desea vincular el valor a un no observable, entonces tomaría un poco más de código. Avísame si eso es algo que necesitas apoyar.
La respuesta aceptada no funcionó para mí con la versión actual del selector de fecha. La entrada no se estaba inicializando con el valor de lo observable. Hice un enlace actualizado, al cual agregué esto:
$(element).datepicker(''update'', dataSource());
Eso parece hacer el truco.
Aquí hay un violín actualizado que usa el último selector de fechas disponible, Bootstrap, jQuery y Knockout: http://jsfiddle.net/krainey/nxhqerxg/
Actualizar:
Experimenté algunas dificultades con el selector de fechas que no jugaba bien con el observable cuando un usuario editaba manualmente el valor en el campo de texto. La herramienta analizará inmediatamente la fecha y conectará el resultado en el campo de entrada.
Si el usuario intentó editar 10/07/2014, por ejemplo, y utilizó el retroceso o eliminar para eliminar un número (10/0/2014), el valor resultante se analizará inmediatamente y se insertará en la entrada de texto. Si el valor fue, por un momento, 10/0/2014, el selector cambiaría el calendario a 30/09/2014 y conectaría ese valor al campo de texto. Si traté de editar el mes, y el valor fue, por un momento, 1/7/2014, el selector cambiaría al 7 de enero de 2014 y conectaría ese valor en el campo de texto.
Puedes ver ese comportamiento en este violín:
http://jsfiddle.net/krainey/nxhqerxg/10/
Tuve que actualizar mi enlace con un controlador especial para detectar el foco y vincular un evento de desenfoque por única vez para que manejara las ediciones manuales correctamente.
$(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);
}
});
El violín al que se hace referencia en la respuesta original se ha actualizado para reflejar esto:
mi versión actual es una mezcla entre las soluciones ya mostradas:
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)
}
}
}};