我正在使用jQuery UI日期选择器。它后面的HTML输入字段当前连接到KnockoutJS作为dependentObservable,但是当它在viewmodel中设置时,datepicker会丢失其格式。
我该怎么做而不会丢失格式?我希望viewModel不要知道它是jQuery datepicker。
答案 0 :(得分:79)
您可以编写一个自定义绑定,使用datepicker API在字段中设置日期,并通过正确读取日期来设置您的observable的值。
自定义绑定可能如下所示:
ko.bindingHandlers.datepicker = {
init: function(element, valueAccessor, allBindingsAccessor) {
var options = allBindingsAccessor().datepickerOptions || {},
$el = $(element);
//initialize datepicker with some optional options
$el.datepicker(options);
//handle the field changing
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),
current = $el.datepicker("getDate");
if (value - current !== 0) {
$el.datepicker("setDate", value);
}
}
};
您可以使用它:
<input data-bind="datepicker: myDate, datepickerOptions: { minDate: new Date() }" />
datepickeroptions
是可选的,可以包含您希望传递到datepicker()
来电的任何内容。
此外,这假设您使用了一个可观察日期。如果你想用一个不可观察的单向绑定,绑定必须做更多的工作,但这不太可能。
答案 1 :(得分:6)
我必须使用dateFormat选项对我的代码中的RP Niemeyer代码进行轻微编辑,替换
$(element).datepicker("getDate")
使用
$(element).val()
因此日期的格式化版本在引擎盖下正确传递。
答案 2 :(得分:6)
我一直在使用RP Niemeyer的代码作为上面的答案,但是因为我一直在使用它,所以我对它进行了一些小改动。我以为我会在这里发帖也许它会帮助别人。它几乎是一样的,唯一的区别是如果元素在页面加载时有一个值,那么它将保留其值。另外,我将$elem
变为一个变量,以便jQuery必须执行的$(element)
处理更少。
ko.bindingHandlers['jqDatePicker'] = {
'init': function(element, valueAccessor, allBindingsAccessor) {
/* Initialize datepicker with some optional options */
var options = allBindingsAccessor().jqDatePickerOptions || {},
prop = valueAccessor(),
$elem = $(element);
prop($elem.val());
$elem.datepicker(options);
/* Handle the field changing */
ko.utils.registerEventHandler(element, "change", function () {
prop($elem.datepicker("getDate"));
});
/* Handle disposal (if KO removes by the template binding) */
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$elem.datepicker("destroy");
});
},
'update': function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
$elem = $(element),
current = $elem.datepicker("getDate");
if (value - current !== 0) {
$elem.datepicker("setDate", value);
}
}
};
答案 3 :(得分:2)
这适用于我特定的环境。我正在运行一个足够新的MVC版本,默认的datetime序列化程序呈现在ISO 8601上(参见 On the nightmare that is JSON Dates. Plus, JSON.NET and ASP.NET Web API )。我的绑定不直接写入日期选择器,而是写入输入标记的“值”属性。
另外,值得注意的是,我正在使用date.js
ko.bindingHandlers.dateValue = {
update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
var value = valueAccessor(),
allBindings = allBindingsAccessor();
var valueUnwrapped = ko.utils.unwrapObservable(value);
var pattern = allBindings.datePattern || 'MM/dd/yyyy';
var date = Date.parse(valueUnwrapped)
$(element).val(date.toString(pattern));
},
init: function(element, valueAccessor, allBindingsAccessor) {
//handle the field changing
ko.utils.registerEventHandler(element, "change", function () {
var observable = valueAccessor();
var date = Date.parse($(element).val());
observable(date.toString("yyyy-MM-ddThh:mm:ss"));
});
}
}
绑定看起来像这样:
<input class="date" type="text" data-bind="dateValue: SomeViewModelDate" />
用于打开datepicker的JavaScript代码:
$(document).ready(function () {
$('.date').datepicker({ dateFormat: "mm/dd/yy" });
});
答案 4 :(得分:0)
一种解决方案是在dependentObservable函数中自己格式化日期。所以你必须在函数中返回类似return viewModel.someOtherObservable()
的东西。格式化返回值。
如果您包含代码,我可以解释更多。
答案 5 :(得分:0)
在dependentObservable中格式化日期(到mm / dd / yyyy)正是我想知道该怎么做。如果你能提供帮助,我会发布一些我的代码,Peter Mortensen和/或nEEBz。
<div data-bind="with: technology">
<div class="titleblock">
<label><b>End of Life Date</b></label>
<Input type="text" class="ui-datepicker" id="datepicker" data-bind="value: END_OF_LIFE_DATE"/>
</div>
</div>
ViewModel中的- technologydetail.js:
var technology = ko.observable();
在激活中:
return dataContext.getTechnologyById(currentTechnologyId, technology);
这会在文本框中显示如下所示的日期:Wed Jan 29 19:00:00 EST 2014 我希望它只显示:2014年1月29日。我正在使用这个datepicker选项 - dateFormat:“mm / dd / yy”但它对显示的初始值没有影响。
我能够使用片刻对其进行格式化,并且它可以很好地显示当前数据库值,但它似乎将绑定重新打开到observable,因为它将不再在SAVE上更新。
<Input type="text" class="ui-datepicker" id="datepicker" data-bind="value: moment(END_OF_LIFE_DATE()).format('MM/DD/YYYY')" />