18

(目前这仅适用于 Chrome,因为大多数浏览器还没有为 input type="date" 实现日期选择器)

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

一旦您在选择器中选择了一个日期,MyDate 就会成为上述格式的字符串。

您如何绑定它,以便 MyDate 保持 javascript Date 并由输入控件正确解释?

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>
4

9 回答 9

10

虽然@amakhrov 答案会起作用(如果使用像@Stijn sujested 这样的可写计算可观察对象会更好)我决定使用Custom Bindings来做到这一点。

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

(阅读此处了解有关执行此类操作的 3 种选择的更多利弊)

HTML

<input data-bind="datePicker : MyDate" type="date">

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);

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

于 2013-08-05T12:39:52.070 回答
7

您可以将计算的变量用于模型中的日期对象:

在 html 中:

<input data-bind="value : rawDate" type="date">

在代码中:

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)

请看演示:http: //jsfiddle.net/gcAXB/1/

于 2013-08-02T12:35:57.707 回答
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>

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

于 2014-05-07T02:33:38.807 回答
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

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

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

并将其显示为

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

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

于 2016-03-04T14:44:44.383 回答
4

此自定义绑定相同,但使用 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");
    }
};
于 2016-04-12T10:39:26.927 回答
3

根据上面 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;
        }
    }
};
于 2014-11-15T00:13:53.660 回答
1

来自HTML 5 - iOS 上的输入类型日期格式

有两种格式在起作用:

  • 显示格式
  • 暴露给 JavaScript 并发送到服务器的内部格式

您无法更改显示格式。由浏览器决定如何向用户显示日期(实际上它由系统的区域设置决定)。

您也不能更改内部格式。无论浏览器/语言环境如何,它始终是 ISO8601。

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

如果您还想从 JS 写入它,您可以设置一个可写的计算 observable并解析输入以查看它是来自输入字段的字符串,还是Date来自您的 JS 的对象。

于 2013-08-02T12:48:18.240 回答
0

这对我有用

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"/>
于 2017-05-02T23:16:58.153 回答
0

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

ko.bindingHandlers.dateTime = {
  // Register change callbacks to update the model if the control changes.
  init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
    ko.utils.registerEventHandler(element, 'change', function () {
      const value = valueAccessor()
      const datetime = DateTime.fromFormat(element.value, 'yyyy-MM-dd')
      value(datetime)
    })
  },
  // Update the control whenever the view model changes
  update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
    const value = valueAccessor()
    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">
于 2021-04-02T04:23:18.090 回答