使用 jquery-ui datepicker 的 knockoutjs 数据绑定
Posted
技术标签:
【中文标题】使用 jquery-ui datepicker 的 knockoutjs 数据绑定【英文标题】:knockoutjs databind with jquery-ui datepicker 【发布时间】:2011-09-17 22:48:26 【问题描述】:我正在使用jQuery UI 日期选择器。它后面的 html 输入字段目前作为dependentObservable 挂接到KnockoutJS,但是当在视图模型中设置它的值时,日期选择器会丢失它的格式。
我应该如何做到这一点而不丢失格式?我希望 viewModel 不知道它是 jQuery datepicker。
【问题讨论】:
【参考方案1】:您可以编写一个自定义绑定,使用 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()
调用的任何内容。
此外,这假设您正在使用可观察的日期。如果您想与不可观察对象进行单向绑定,则绑定必须做更多的工作,但这不太可能。
示例:http://jsfiddle.net/rniemeyer/NAgNV/
【讨论】:
这个自定义绑定需要如何更改才能更好地在 datepicker 和“with: submodelObject”样式绑定之间进行协作?在我的使用中,它导致日期选择器的 div 最终呈现为可见,直到它可以附加到可见的 ;不过,使用“模板:afterRender:jqueryDecoratingMethod,数据:submodelObject”效果很好。 @TetsujinnoOni 你有你在哪里看到问题的样本吗?很乐意看看。 Ryan - 感谢您的提议;我无法在小提琴中重现。我怀疑(由于页面上的其他丑陋)我要么忘记了主题 jqueryui 要么在我的 CSS 中发生了类似的丑陋......如果我可以将其缩小到特定的因素组合,我会发布一个链接或一个小提琴。 我意识到这已经很老了,但是当我尝试将它用于日期时间选择器时,在 IE7 中,弹出窗口不会完全消失。当我选择一个值时,它会短暂隐藏弹出窗口,然后再次激活,没有任何方法可以关闭它。对这个错误有什么想法吗?在 Chrome 中似乎很好。 @Zero21xxx 我更新了答案并进行了调整,以防止在 IE7 上出现此问题。这在某个时候出现在另一个问题中。【参考方案2】:我必须对 RP Niemeyer 的代码稍作修改才能使用 dateFormat 选项在我的代码中工作,替换
$(element).datepicker("getDate")
有
$(element).val()
因此,日期的格式化版本在后台正确传递。
【讨论】:
【参考方案3】:我一直在使用上面标记为答案的 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);
;
【讨论】:
我没有深入研究,但是日期选择器的初始值没有设置为绑定的 observable 的值。【参考方案4】:以下是适合我特定情况的方法。我正在运行一个足够新的 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" );
);
【讨论】:
我有一个问题,我应该在应用绑定之前将代码放在哪里?现在我收到错误:未捕获类型错误:无法处理绑定“foreach:函数()返回策略”消息:无法处理绑定“dateValue:函数()return startDate”消息:无法读取属性'toString ' 为空【参考方案5】:当用户从 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);
;
【讨论】:
【参考方案6】:一种解决方案是在dependentObservable 函数中自己格式化日期。所以你必须在函数中返回类似return viewModel.someOtherObservable()
的东西。格式化返回值。
如果你包含你的代码,我可以解释更多。
【讨论】:
【参考方案7】:在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')" />
【讨论】:
以上是关于使用 jquery-ui datepicker 的 knockoutjs 数据绑定的主要内容,如果未能解决你的问题,请参考以下文章
Laravel 5.5 中的 Datepicker 使用 Jquery-ui 或 Bootstrap
如何使用 NPM 同时获得 JQuery-UI 和 datepicker 本地化?
使用 jquery-ui datepicker 的 knockoutjs 数据绑定
jquery-ui datepicker 设置开始结束时间选择范围
在 jquery-ui datepicker 中的“今天”按钮上添加事件侦听器
Rails 服务器告诉我 --- 找不到类型为 'application/javascript' 的文件 'jquery-ui/datepicker'