使用Knockout.js如何将Date属性绑定到HTML5日期选择器
Using Knockout.js how do bind a Date property to a HTML5 date picker?
(目前这只适用于Chrome,因为大多数浏览器还没有实现输入类型="date"的日期选择器)
在下面的示例中,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>
虽然@amakhrov的答案会起作用(如果像@Stijn所说的那样使用可写计算可观察的答案会更好),但我决定使用自定义绑定来完成这项工作。
这样做的主要优点是可重用性-我只需要在任何想将其绑定的地方使用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/
您可以使用模型中日期对象的计算变量:
在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/
这是一个适用于我的最新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>
使用敲除和矩JS 绑定和格式化日期
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");
}
};
根据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;
}
}
};
从HTML 5-iOS 上的输入类型日期格式
有两种格式在发挥作用:
- 显示格式
- 向JavaScript公开并发送到服务器的内部格式
无法更改显示格式。由浏览器决定如何向用户显示日期(在实践中,由系统的区域设置)。
您也不能更改内部格式。它总是ISO8601,无论浏览器/区域设置如何。
您必须用特定的格式预先填充它,并且可以添加一个计算的可观察对象来将其解析为Date
对象,这样您就可以在应用程序的其他位置读取它。
如果你也想从JS中写入,你可以设置一个可写的可计算的可观察对象,并解析输入,看看它是来自输入字段的字符串,还是来自JS的Date
对象。
这对我有效
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"/>
这可能很晚了,但可能会对外面的人有所帮助。我使用Luxon的DateTime
对象来轻松管理应用程序中的日期和时区。这适用于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">
- 在VanillaJS中模拟模型双向数据绑定
- 无法通过数组映射绑定
- 主干-不管怎样,检查事件以前是否绑定过
- 用于搜索的聚合物嵌套绑定
- Angular:更新一次性绑定的数据
- 如何使用ngrepeat和双向绑定获得指令的隔离范围
- react.js中的密钥绑定
- 使用regex的jquery keydown绑定不会验证撇号和句点
- 将事件处理程序绑定到任何可能的事件
- AngularJS指令只识别双向绑定类型
- Telerik rad组合框多列数据绑定
- 单选按钮选中绑定 HTML5,杜兰达尔
- 将挖空值绑定到 HTML5 日期选取器 (Chrome)
- 使用Knockout.js如何将Date属性绑定到HTML5日期选择器
- '已结束'HTML5事件未绑定到绑定后创建的元素上
- BootStrap -模型绑定和HTML5/CSS3支持
- 如何使用Knockout.js绑定HTML5日期选择器和其他输入类型
- 如何在HTML5中将事件绑定到数据值更改
- HTML5/Javascript -尝试将画布动画绑定到键盘事件
- 如何从不支持HTML5的旧浏览器绑定到web sockets服务器