【发布时间】:2011-09-17 22:48:26
【问题描述】:
我正在使用jQuery UI 日期选择器。它后面的 HTML 输入字段目前作为dependentObservable 挂接到KnockoutJS,但是当在视图模型中设置它的值时,日期选择器会丢失它的格式。
我应该如何做到这一点而不丢失格式?我希望 viewModel 不知道它是 jQuery datepicker。
【问题讨论】:
标签: jquery-ui knockout.js
我正在使用jQuery UI 日期选择器。它后面的 HTML 输入字段目前作为dependentObservable 挂接到KnockoutJS,但是当在视图模型中设置它的值时,日期选择器会丢失它的格式。
我应该如何做到这一点而不丢失格式?我希望 viewModel 不知道它是 jQuery datepicker。
【问题讨论】:
标签: jquery-ui knockout.js
您可以编写一个自定义绑定,使用 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() 调用的任何内容。
此外,这假设您正在使用可观察的日期。如果您想与不可观察对象进行单向绑定,则绑定必须做更多的工作,但这不太可能。
【讨论】:
我必须对 RP Niemeyer 的代码稍作修改才能使用 dateFormat 选项在我的代码中工作,替换
$(element).datepicker("getDate")
有
$(element).val()
因此,日期的格式化版本在后台正确传递。
【讨论】:
我一直在使用上面标记为答案的 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);
}
}
};
【讨论】:
以下是适合我特定情况的方法。我正在运行一个足够新的 MVC 版本,默认日期时间序列化程序以 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" />
以及开启日期选择器的 JavaScript 代码:
$(document).ready(function () {
$('.date').datepicker({ dateFormat: "mm/dd/yy" });
});
【讨论】:
当用户从 datepicker 控件中选择新日期时,上面的 datepicker 示例将 viewmodel 中的日期格式从 WCF 格式更改为 JavaScript 日期格式。
在我的例子中,我将日期传递回 WCF 服务,它不接受反序列化的 JavaScript 日期,它需要 WCF 格式的日期。我修改了上面的脚本,以便它以 WCF 格式将日期存储在视图模型中,以便可以以该格式将其发送回服务器。
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).datepicker("getDate"));
// store the date in 'WCF String format"
var tempdate=$(element).datepicker("getDate");
var tempdatestr="/Date("+tempdate.getTime()+")/";
observable(tempdatestr);
});
//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);
}
}
};
【讨论】:
一种解决方案是在dependentObservable 函数中自己格式化日期。所以你必须在函数中返回类似return viewModel.someOtherObservable() 的东西。格式化返回值。
如果你包含你的代码,我可以解释更多。
【讨论】:
在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 但是 我希望它只显示:01/29/2014。我正在使用这个 datepicker 选项 - dateFormat: "mm/dd/yy" 但它对显示的初始值没有影响。
我能够使用 moment 对其进行格式化,并且它可以很好地显示当前数据库值,但它似乎正在破坏与 observable 的绑定,因为它将不再在 SAVE 上更新。
<Input type="text" class="ui-datepicker" id="datepicker" data-bind="value: moment(END_OF_LIFE_DATE()).format('MM/DD/YYYY')" />
【讨论】: