Jquery ui KnockoutJS未捕获jQuery UI日期选择器更改事件
我正在尝试将KnockoutJS与jqueryui一起使用。我有一个带有日期选择器的输入元素。我目前正在运行Jquery ui KnockoutJS未捕获jQuery UI日期选择器更改事件,jquery-ui,knockout.js,Jquery Ui,Knockout.js,我正在尝试将KnockoutJS与jqueryui一起使用。我有一个带有日期选择器的输入元素。我目前正在运行knockout.debug.1.2.1.js,似乎knockout永远不会捕捉到更改事件。元素如下所示: 我甚至尝试过更改valueUpdate事件类型,但没有效果。Chrome似乎在更改值之前引发了一个focus事件,但IE没有 是否有某种淘汰方法可以“重新绑定所有绑定”?从技术上讲,我只需要在将值发送回服务器之前更改它。这样我就可以适应这种工作环境了 我认为问题出在日期选取者的错
knockout.debug.1.2.1.js
,似乎knockout永远不会捕捉到更改事件。元素如下所示:
我甚至尝试过更改valueUpdate
事件类型,但没有效果。Chrome似乎在更改值之前引发了一个focus
事件,但IE没有
是否有某种淘汰方法可以“重新绑定所有绑定”?从技术上讲,我只需要在将值发送回服务器之前更改它。这样我就可以适应这种工作环境了
我认为问题出在日期选取者的错误上,但我不知道如何解决这个问题
有什么想法吗?我认为对于jQuery UI datepicker,最好使用自定义绑定,使用datepicker提供的API对日期对象进行读/写 从我的回答来看,绑定可能如下所示: 你会像这样使用它:
<input data-bind="datepicker: myDate, datepickerOptions: { minDate: new Date() }" />
JSFIDLE中的示例:我认为可以更轻松地完成:
因此,在init函数中不需要手动更改处理
但在这种情况下,“myDate”变量将只获得可见值,而不是日期对象。感谢本文,我发现它非常有用 如果希望DatePicker的行为与JQuery UI默认行为完全相同,我建议在更改事件处理程序中的元素上添加模糊: i、 e
或者,您可以在绑定中指定: 更新:
function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
current = $(element).datepicker("getDate");
if (typeof value === "string") {
var dateValue = new Date(value);
if (dateValue - current !== 0)
$(element).datepicker("setDate", dateValue);
}
}
以下是RP Niemeyer答案的一个版本,它将与此处找到的淘汰验证脚本一起使用: 对更改事件处理程序进行更改,首先将输入的值而不是日期传递给验证脚本,然后仅将日期设置为有效的可观察日期。我还添加了此处讨论的自定义绑定所需的validationCore.init:
我还添加了rpenrose关于更改时模糊的建议,以消除一些令人讨厌的日期选择器场景阻碍事情的发展。我使用了不同的方法。由于knockout.js似乎不会在更改时触发事件,因此我强制datepicker在关闭后为其输入调用change()
$(".date").datepicker({
onClose: function() {
$(this).change(); // Forces re-validation
}
});
与RP Niemeyer相同,但更好地支持WCF DateTime、时区和使用DatePicker onSelect JQuery属性
ko.bindingHandlers.datepicker = {
init: function (element, valueAccessor, allBindingsAccessor) {
//initialize datepicker with some optional options
var options = allBindingsAccessor().datepickerOptions || {};
var funcOnSelectdate = function () {
var observable = valueAccessor();
var d = $(element).datepicker("getDate");
var timeInTicks = d.getTime() + (-1 * (d.getTimezoneOffset() * 60 * 1000));
observable("/Date(" + timeInTicks + ")/");
}
options.onSelect = funcOnSelectdate;
$(element).datepicker(options);
//handle the field changing
ko.utils.registerEventHandler(element, "change", funcOnSelectdate);
//handle disposal (if KO removes by the template binding)
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).datepicker("destroy");
});
},
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);
}
}
};
享受:)
虽然所有这些答案都为我节省了大量工作,但没有一个完全适合我。选择日期后,绑定值不会更新。我只能在使用键盘更改日期值,然后从输入框中单击时更新它。我通过使用syb的代码扩充RP Niemeyer的代码来修复此问题,以获得:
ko.bindingHandlers.datepicker = {
init: function (element, valueAccessor, allBindingsAccessor) {
//initialize datepicker with some optional options
var options = allBindingsAccessor().datepickerOptions || {};
var funcOnSelectdate = function () {
var observable = valueAccessor();
observable($(element).datepicker("getDate"));
}
options.onSelect = funcOnSelectdate;
$(element).datepicker(options);
//handle the field changing
ko.utils.registerEventHandler(element, "change", funcOnSelectdate);
//handle disposal (if KO removes by the template binding)
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).datepicker("destroy");
});
},
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
if (typeof(value) === "string") { // JSON string from server
value = value.split("T")[0]; // Removes time
}
var current = $(element).datepicker("getDate");
if (value - current !== 0) {
var parsedDate = $.datepicker.parseDate('yy-mm-dd', value);
$(element).datepicker("setDate", parsedDate);
}
}
};
我怀疑将可观察($(元素).datepicker(“getDate”);语句,并将其注册到options.onSelect中。根据Ryan的解决方案,myDate返回标准日期字符串,这在我的示例中不是理想的。我使用date.js解析该值,因此它将始终返回您想要的日期格式。看看这个例子
我通过更改包含的脚本文件的顺序解决了此问题:
<script src="@Url.Content("~/Scripts/jquery-ui-1.10.2.custom.js")"></script>
<script src="@Url.Content("~/Scripts/knockout-2.2.1.js")"></script>
我需要反复更新服务器上的数据,但我没有完全完成以下需要共享的工作(我的日期格式/日期(1224043200000)/): 在为输出正确格式化模型后,我添加了一个带有文档的模板:
//内联模板
很少有人要求提供动态日期选择器选项。在我的例子中,我需要一个动态的日期范围——因此第一个输入定义了第二个的最小值,第二个设置了第一个的最大值。我通过扩展RP Niemeyer的处理器解决了这个问题。因此,对于他的原作:
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, "change", 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);
}
}
};
我还添加了两个与我要修改的选项相对应的处理程序:
ko.bindingHandlers.minDate = {
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
current = $(element).datepicker("option", "minDate", value);
}
};
ko.bindingHandlers.maxDate = {
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
current = $(element).datepicker("option", "maxDate", value);
}
};
并在我的模板中这样使用它们:
<input data-bind="datepicker: selectedLowerValue, datepickerOptions: { minDate: minValue()}, maxDate: selectedUpperValue" />
<input data-bind="datepicker: selectedUpperValue, datepickerOptions: { maxDate: maxValue()}, minDate: selectedLowerValue" />
使用前面答案中提供的自定义绑定并不总是可行的。调用
$(element).datepicker(…)
需要相当长的时间,例如,如果您有几十个甚至数百个元素要调用此方法,则必须“延迟”,即按需执行
例如,可以初始化视图模型,将输入插入DOM中,但是只有当用户单击相应的日期选择器时,才会初始化它们
因此,以下是我的解决方案:
添加允许将任意数据附加到节点的自定义绑定:
KO.bindingHandlers.boundData = {
init: function(element, __, allBindings) {
element.boundData = allBindings.get('boundData');
}
};
使用绑定来附加用于输入的可观察值:
<input type='text' class='my-date-input'
data-bind='textInput: myObservable, boundData: myObservable' />
这样,每当用户使用datepicker更改日期时,相应的淘汰观测值也会更新。我喜欢的是,您没有像dispose回调那样在这个活页夹中抄近路。一个良好的例子,遵循的道路上击倒JS掌握!那么绑定到一个动态创建的元素的日期选择器呢。。。我的意思是,具有实时处理程序的日期采集器。Phoenix_uy:要让日期采集器处理动态创建的对象,请确保不要设置输入的ID或名称。我正在使用它,它工作得很好,除了一件小事——如果我将minDate或maxDate设置为可观察对象,则如果该可观察对象发生更改,它不会得到更新(例如,如果我有两个日期选择器,其中第一个的最大日期是第二个的值,如果我更新第二个,则它不会更新第一个的最大日期)与此问题相同,看起来事件名称是错误的,ko.utils.registerEventHandler(元素,“changeDate”,函数()-应该是ko.utils.registerEventHandler(元素,“change”,函数()此答案看起来不完整?这是对@RPNiemeyer的答案的注释,还是对其他人的答案的注释?这修复了返回日期值为
<div id="documentsContainer">
<div data-bind="template: { name: 'document-template', foreach: documents, afterRender: afterRenderLogic }, visible: documents().length > 0"></div>
</div>
//Inline template
<script type="text/html" id="document-template">
<input data-bind="value: RedemptionExpiration" class="datepicker" />
</script>
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, "change", 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);
}
}
};
ko.bindingHandlers.minDate = {
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
current = $(element).datepicker("option", "minDate", value);
}
};
ko.bindingHandlers.maxDate = {
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
current = $(element).datepicker("option", "maxDate", value);
}
};
<input data-bind="datepicker: selectedLowerValue, datepickerOptions: { minDate: minValue()}, maxDate: selectedUpperValue" />
<input data-bind="datepicker: selectedUpperValue, datepickerOptions: { maxDate: maxValue()}, minDate: selectedLowerValue" />
KO.bindingHandlers.boundData = {
init: function(element, __, allBindings) {
element.boundData = allBindings.get('boundData');
}
};
<input type='text' class='my-date-input'
data-bind='textInput: myObservable, boundData: myObservable' />
$('.my-date-input').datepicker({
onSelect: function(dateText) {
this.myObservable(dateText);
}
//Other options
});