使用Knockout.js如何将Date属性绑定到HTML5日期选择器?

Rya*_*yan 16 javascript html5 knockout.js

(目前仅适用于Chrome,因为大多数浏览器尚未为输入类型="日期"实现日期选择器)

在下面的示例中,MyDate以具有当前日期的Date对象开始,但日期输入(它希望其格式为格式为YYYY/MM/DD的字符串)不会选择此项.

一旦你在选择器中选择了一个日期,MyDate就会变成上面格式的字符串.

如何绑定这个,以便MyDate保持javascript日期并由输入控件正确解释?

http://jsfiddle.net/LLkC4/3/: -

<input data-bind="value : MyDate" type="date">
<hr>   
<span data-bind="html: log" />

<script>
var viewModel = {    
    MyDate : ko.observable(new Date()),
    log : ko.observable(""),
    logDate : function () { 
            this.log(this.log() + this.MyDate() + " : " +
                     typeof(this.MyDate()) + "<br>");
                     }
};

viewModel.MyDate.subscribe(function (date) {    
    viewModel.logDate();    
});

ko.applyBindings(viewModel);

viewModel.logDate()
</script>
Run Code Online (Sandbox Code Playgroud)

Rya*_*yan 9

虽然@amakhrov的答案会起作用(如果使用像@Stijn那样使用可写的计算可观察量会更好)我决定使用自定义绑定来做到这一点.

这样做的主要优点是可重用性 - 我只需要使用data-bind="datePicker : MyDate"我想要绑定它.我还可以修改输入元素的其他属性,这样如果绑定到复杂的jQuery(和其他)控件,这可能非常有用.

(请阅读此处了解更多有关做出此类事情的3种选择的赞成/反对意见)

HTML

<input data-bind="datePicker : MyDate" type="date">
Run Code Online (Sandbox Code Playgroud)

JS

ko.bindingHandlers.datePicker = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {                    
        // Register change callbacks to update the model
        // if the control changes.       
        ko.utils.registerEventHandler(element, "change", function () {            
            var value = valueAccessor();
            value(new Date(element.value));            
        });
    },
    // Update the control whenever the view model changes
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var value =  valueAccessor();        
        element.value = value().toISOString();
    }
};

var viewModel = {    
    MyDate : ko.observable(new Date())
};     

ko.applyBindings(viewModel);
Run Code Online (Sandbox Code Playgroud)

http://jsfiddle.net/LLkC4/5/

  • 这仍然适合你吗?我的chrome datepicker拒绝显示任何日期 - 即使我选择新日期,甚至当它们显示在您的日志打印输出中时,框中只显示"mm/dd/yyyy".你知道怎么解决吗?我正在挣扎. (5认同)

ama*_*rov 7

您可以在模型中使用计算的vartiable作为日期对象:

在html中:

<input data-bind="value : rawDate" type="date">
Run Code Online (Sandbox Code Playgroud)

在代码中:

var currentDate = (new Date()).toISOString().split('T')[0];

// this is used instead of MyDate in the data binding
rawDate : ko.observable(currentDate),

...
// and then set up the dependent variable
viewModel.MyDate = ko.computed(function () {
    var val = this.rawDate();
    if (typeof val === 'string') val = new Date(val);

    return val;
}, viewModel)
Run Code Online (Sandbox Code Playgroud)

请参阅演示:http://jsfiddle.net/gcAXB/1/


Jus*_*tin 6

这是一个解决方案,使用最新的knockoutjs,根据下面的链接,并修改为具有自定义初始化函数来处理日期值更改时更新ko.computed属性.

请注意,utils.formatDate只是一个实用程序函数,用于以您想要的任何字符串格式化日期,因此只需将其替换为您自己的日期格式代码,无论您使用的是momentjs还是其他内容.

ko.bindingHandlers.date = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {    
        ko.utils.registerEventHandler(element, 'change', function () {
            var value = valueAccessor();

            if (element.value !== null && element.value !== undefined && element.value.length > 0) {
                value(element.value);
            }
            else {
                value('');
            }
        });
    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var value = valueAccessor();
        var valueUnwrapped = ko.utils.unwrapObservable(value);

        var output = '';
        if (valueUnwrapped !== null && valueUnwrapped !== undefined && valueUnwrapped.length > 0) {
            output = utils.formatDate(valueUnwrapped);
        }

        if ($(element).is('input') === true) {
            $(element).val(output);
        } else {
            $(element).text(output);
        }
    }
};

    <div>
        <label>Date of Birth:</label>
        <input type="text" data-bind="date: dateOfBirth, format: 'DD MMM YYYY'" />
    </div>
Run Code Online (Sandbox Code Playgroud)

使用KNOCKOUT和MOMENT JS绑定和格式化日期


bri*_*itt 5

现在使用 Moment.js 变得容易多了

this.sessionDate = ko.observable(moment().format('YYYY-MM-DD'));
this.getFormattedDate = () => { return moment(this.sessionDate()'YYYY-MM-DD').format('MM/DD/YYYY') }; // Note this is ES2015 syntax
Run Code Online (Sandbox Code Playgroud)

在您的 html 中,您可以将其绑定

<input class="form-control" name="date" type="date" id="date" data-bind="value: sessionDate">
Run Code Online (Sandbox Code Playgroud)

并将其显示为格式

<p data-bind="text : getFormattedDate()">Loading Date</p>
Run Code Online (Sandbox Code Playgroud)

无需创建自定义绑定,您可以为旧浏览器使用 shim。

  • 我认为这应该是新的答案,就像一个魅力。 (2认同)