使用jquery-ui datepicker敲击数据绑定

时间:2011-06-18 21:47:18

标签: jquery-ui knockout.js

我正在使用jQuery UI日期选择器。它后面的HTML输入字段当前连接到KnockoutJS作为dependentObservable,但是当它在viewmodel中设置时,datepicker会丢失其格式。

我该怎么做而不会丢失格式?我希望viewModel不要知道它是jQuery datepicker。

6 个答案:

答案 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()来电的任何内容。

此外,这假设您使用了一个可观察日期。如果你想用一个不可观察的单向绑定,绑定必须做更多的工作,但这不太可能。

此处示例:http://jsfiddle.net/rniemeyer/NAgNV/

答案 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')" />