KnockoutJS no detecta el evento de cambio del selector de fechas de jQuery UI
Estoy intentando usar KnockoutJS con jQuery UI. Tengo un elemento de entrada con un selector de fecha adjunto. Actualmente estoy corriendo knockout.debug.1.2.1.js
y parece que Knockout nunca detecta el evento de cambio. El elemento se ve así:
<input type="text" class="date" data-bind="value: RedemptionExpiration"/>
Incluso intenté cambiar el valueUpdate
tipo de evento pero fue en vano. Parece que Chrome causa unfocus
evento justo antes de cambiar el valor, pero IE no.
¿Existe algún método Knockout que "vuelva a vincular todos los enlaces"? Técnicamente solo necesito cambiar el valor antes de enviarlo de vuelta al servidor. Entonces podría vivir con ese tipo de solución.
Creo que el problema es culpa del selector de fechas, pero no sé cómo solucionarlo.
¿Algunas ideas?
Creo que para el selector de fechas de jQuery UI es preferible usar un enlace personalizado que lea/escriba con objetos Date usando las API proporcionadas por el selector de fechas.
El enlace podría verse así (según mi respuesta aquí ):
ko.bindingHandlers.datepicker = {
init: function(element, valueAccessor, allBindingsAccessor) {
//initialize datepicker with some optional options
var options = allBindingsAccessor().datepickerOptions || {},
$el = $(element);
$el.datepicker(options);
//handle the field changing by registering datepicker's changeDate event
ko.utils.registerEventHandler(element, "changeDate", function () {
var observable = valueAccessor();
observable($el.datepicker("getDate"));
});
//handle disposal (if KO removes by the template binding)
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$el.datepicker("destroy");
});
},
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
$el = $(element);
//handle date data coming via json from Microsoft
if (String(value).indexOf('/Date(') == 0) {
value = new Date(parseInt(value.replace(/\/Date\((.*?)\)\//gi, "$1")));
}
var current = $el.datepicker("getDate");
if (value - current !== 0) {
$el.datepicker("setDate", value);
}
}
};
Lo usarías como:
<input data-bind="datepicker: myDate, datepickerOptions: { minDate: new Date() }" />
Muestra en jsFiddle aquí: http://jsfiddle.net/rniemeyer/NAgNV/
Aquí hay una versión de la respuesta de RP Niemeyer que funcionará con los scripts de validación de knockout que se encuentran aquí: http://github.com/ericmbarnard/Knockout-Validation
ko.bindingHandlers.datepicker = {
init: function (element, valueAccessor, allBindingsAccessor) {
//initialize datepicker with some optional options
var options = allBindingsAccessor().datepickerOptions || {};
$(element).datepicker(options);
//handle the field changing
ko.utils.registerEventHandler(element, "change", function () {
var observable = valueAccessor();
observable($(element).val());
if (observable.isValid()) {
observable($(element).datepicker("getDate"));
$(element).blur();
}
});
//handle disposal (if KO removes by the template binding)
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).datepicker("destroy");
});
ko.bindingHandlers.validationCore.init(element, valueAccessor, allBindingsAccessor);
},
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
//handle date data coming via json from Microsoft
if (String(value).indexOf('/Date(') == 0) {
value = new Date(parseInt(value.replace(/\/Date\((.*?)\)\//gi, "$1")));
}
current = $(element).datepicker("getDate");
if (value - current !== 0) {
$(element).datepicker("setDate", value);
}
}
};
Los cambios son para que el controlador de eventos de cambio pase primero el valor ingresado y no la fecha a los scripts de validación, y luego solo establezca la fecha en el observable si es válida. También agregué validationCore.init que se necesita para los enlaces personalizados que se analizan aquí:
http://github.com/ericmbarnard/Knockout-Validation/issues/69
También agregué la sugerencia de rpenrose de desenfocar el cambio para eliminar algunos escenarios molestos del selector de fechas que interfieren con las cosas.