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

Javascript 使用Knockout.js如何将日期属性绑定到HTML5日期选择器?,javascript,html,knockout.js,Javascript,Html,Knockout.js,(目前这只适用于Chrome,因为大多数浏览器尚未为输入type=“date”实现日期选择器) 在下面的示例中,MyDate以当前日期的日期对象开始,但日期输入不会拾取该对象(它的格式应为YYYY/MM/DD格式的字符串) 一旦在选择器中选择了日期,MyDate就会变成上面格式的字符串 如何绑定它,使MyDate保持为javascript日期,并由输入控件正确解释 见:- var viewModel={ MyDate:ko.可观察(新日期()), 对数:ko.可观察(“”), logDate

(目前这只适用于Chrome,因为大多数浏览器尚未为输入type=“date”实现日期选择器)

在下面的示例中,MyDate以当前日期的日期对象开始,但日期输入不会拾取该对象(它的格式应为YYYY/MM/DD格式的字符串)

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

如何绑定它,使MyDate保持为javascript日期,并由输入控件正确解释

见:-



var viewModel={ MyDate:ko.可观察(新日期()), 对数:ko.可观察(“”), logDate:函数(){ this.log(this.log()+this.MyDate()+“:”+ typeof(this.MyDate())+“
”; } }; viewModel.MyDate.subscribe(函数(日期){ viewModel.logDate(); }); 应用绑定(视图模型); viewModel.logDate()
您可以为模型中的日期对象使用计算变量:

在html中:

<input data-bind="value : rawDate" type="date">
请参见演示:

来自

目前有两种格式:

  • 显示格式
  • 暴露于JavaScript并发送到服务器的内部格式
无法更改显示格式。由浏览器决定 如何向用户显示日期(实际上,日期由 系统的区域设置)

您也不能更改内部格式。它总是ISO8601, 不考虑浏览器/区域设置

您必须使用该特定格式预先填充它,并且您可以添加一个计算的可观察对象来将其解析为
Date
对象,以便您可以在应用程序中的其他位置读取它


如果您还想从JS向它写入数据,您可以设置并解析输入,查看它是来自输入字段的字符串,还是JS中的
Date
对象。

而@amakhrov answer将起作用(如果使用@Stijn提供的sujested这样的可写计算可观察对象,效果会更好),我决定使用

这样做的主要优点是可重用性——我只需使用
data bind=“datePicker:MyDate”
就可以了。我还可以修改输入元素的其他属性,这样,如果绑定到复杂的jQuery(和其他)控件,这将非常有用

(关于做这类事情的3种选择)

HTML


请参见

这里有一个最新的knockoutjs解决方案,它基于下面的链接,经过修改,具有一个自定义的init函数,可以在日期值更改时更新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>
ko.bindingHandlers.date={
init:function(元素、valueAccessor、allBindingsAccessor、viewModel){
ko.utils.registerEventHandler(元素'change',函数(){
var value=valueAccessor();
if(element.value!==null&&element.value!==undefined&&element.value.length>0){
价值(元素价值);
}
否则{
价值(“”);
}
});
},
更新:函数(元素、valueAccessor、allBindingsAccessor、viewModel){
var value=valueAccessor();
var valueUnwrapped=ko.utils.unwrapObservable(值);
var输出=“”;
if(valueUnwrapped!==null&&valueUnwrapped!==undefined&&valueUnwrapped.length>0){
输出=utils.formatDate(valueUnwrapped);
}
if($(元素).is('input')==true){
$(元素).val(输出);
}否则{
$(元素)。文本(输出);
}
}
};
出生日期:

根据Ryan的上述回答,这对于更新的ko/chrome小部件来说效果更好。它还去除了日期的时间部分

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();
            var target_date = element.valueAsDate;
            var truncated = new Date(target_date.getFullYear(), target_date.getMonth(), target_date.getDate());
            value(truncated);
        });
    },
    // Update the control whenever the view model changes
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var value =  valueAccessor();
        var unwrapped = ko.utils.unwrapObservable(value());
        if(unwrapped === undefined || unwrapped === null) {
            element.value = '';
        } else {
            element.valueAsDate = unwrapped;
        }
    }
};

现在使用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
在html中,您可以使用

<input class="form-control" name="date" type="date" id="date" data-bind="value: sessionDate">

并将其格式化为

<p data-bind="text : getFormattedDate()">Loading Date</p>
加载日期

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

与相同,但使用momentJS:

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(moment(element.value).format());
        });
    },
    // Update the control whenever the view model changes
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var value =  valueAccessor();
        element.value = moment(value()).format("YYYY-MM-DD");
    }
};
这对我有用

ko.bindingHandlers.momentDate = {
_parseDateTime: function (element, valueAccessor) {
    var value = valueAccessor();
    var valueUnwrapped = ko.utils.unwrapObservable(value);
    var datetime = moment(valueUnwrapped);
    var date = moment($(element).val(), 'YYYY-MM-DD');
    datetime = datetime.set({
        'year': date.get('year'),
        'month': date.get('month'),
        'date': date.get('date')
    });
    value(datetime.toDate());
},
init: function (element, valueAccessor) {
    function bind() {
        ko.bindingHandlers.momentDate._parseDateTime(element, valueAccessor);
    }
    $(element).change(bind).blur(bind);
},
update: function (element, valueAccessor) {
    var value = valueAccessor();
    var valueUnwrapped = ko.utils.unwrapObservable(value);
    var date = moment(valueUnwrapped);
    $(element).val(date.format('YYYY-MM-DD'));
}
})


这可能已经晚了,但它可能会帮助其他人。我正在使用的
DateTime
对象轻松管理应用程序中的日期和时区。这适用于DateTime对象:

ko.bindingHandlers.dateTime={
//注册更改回调以在控件更改时更新模型。
init:函数(元素、valueAccessor、allBindingsAccessor、viewModel){
ko.utils.registerEventHandler(元素'change',函数(){
常量值=值访问器()
const datetime=datetime.fromFormat(element.value,“yyyy-MM-dd”)
值(日期时间)
})
},
//每当视图模型更改时更新控件
更新:函数(元素、valueAccessor、allBindingsAccessor、viewModel){
常量值=值访问器()
element.value=ko.unwrap(value.toFormat('yyyy-MM-dd'))
}
}
用法:

// viewmodel
const today = DateTime.fromFormat(DateTime.now().toFormat('yyyy-MM-dd'), 'yyyy-MM-dd')
this.date = ko.observable(today)

// template
<input type="date" data-bind="dateTime: date">
//视图模型
const today=DateTime.fromFormat(DateTime.now().toFormat('yyyy-MM-dd'),'yyyy-MM-dd'))
this.date=ko.可观察(今天)
//模板

在初始加载时没有设置选择器的值-必须将rawDate设置为ISO格式的MyDate字符串?你说得对。原始示例中没有显示日期,因此我忘了添加:)请查看上面更新的代码和演示。感谢您的回答,您能告诉我如何使用html5 datepicker(输入类型“date”)和knockout.js而不使用计算变量吗?就像在这里做的那样:这对你仍然有效吗?
<p data-bind="text : getFormattedDate()">Loading Date</p>
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(moment(element.value).format());
        });
    },
    // Update the control whenever the view model changes
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var value =  valueAccessor();
        element.value = moment(value()).format("YYYY-MM-DD");
    }
};
ko.bindingHandlers.momentDate = {
_parseDateTime: function (element, valueAccessor) {
    var value = valueAccessor();
    var valueUnwrapped = ko.utils.unwrapObservable(value);
    var datetime = moment(valueUnwrapped);
    var date = moment($(element).val(), 'YYYY-MM-DD');
    datetime = datetime.set({
        'year': date.get('year'),
        'month': date.get('month'),
        'date': date.get('date')
    });
    value(datetime.toDate());
},
init: function (element, valueAccessor) {
    function bind() {
        ko.bindingHandlers.momentDate._parseDateTime(element, valueAccessor);
    }
    $(element).change(bind).blur(bind);
},
update: function (element, valueAccessor) {
    var value = valueAccessor();
    var valueUnwrapped = ko.utils.unwrapObservable(value);
    var date = moment(valueUnwrapped);
    $(element).val(date.format('YYYY-MM-DD'));
}
<input type="date" data-bind="momentDate: $data.Date" class="form-control"/>
// viewmodel
const today = DateTime.fromFormat(DateTime.now().toFormat('yyyy-MM-dd'), 'yyyy-MM-dd')
this.date = ko.observable(today)

// template
<input type="date" data-bind="dateTime: date">