使用knockout将日期值绑定到文本框时出现问题,如下图所示
首次加载页面时,我使用ajax获取AccountStatements数据。
function AccountStatementViewModel(companyID) {
var self = this;
...
var AccountStatement = {
AccountStatementID: self.AccountStatementID,
CompanyID: self.CompanyID,
Description: self.Description,
Amount: self.Amount,
ReceiptDate: self.ReceiptDate,
Type: self.Type
}
self.AccountStatement = ko.observable();
self.AccountStatements = ko.observableArray();
$.ajax({
url: webroot + 'AccountStatement/GetAccountStatements',
contentType: 'application/json; charset=utf-8',
data: { id: self.CompanyID },
cache: false
}).done(function (data) {
self.AccountStatements(data);
});
...
self.edit = function (accountStatement) {
$('#lnkAddAccountStatement').hide('blind', 1000);
$('#pnlAddEditAccountStatement').show('blind', 1000);
self.AccountStatement(accountStatement);
}
...
}
Controller在json中返回结果:
public JsonResult GetAccountStatements(int id)
{
var accountStatementsVM = db.AccountStatements
.Where(a => a.CompanyID == id)
.Select(a => new AccountStatementViewModel
{
AccountStatementID = a.AccountStatementID,
CompanyID = a.CompanyID,
Description = a.Description,
Amount = a.Amount,
ReceiptDate = a.ReceiptDate,
Type = a.Type
})
.ToList();
return Json(accountStatementsVM, JsonRequestBehavior.AllowGet);
}
结果是:
[{"AccountStatementID":2,"CompanyID":1,"Description":"test","Amount":1000,"ReceiptDate":"/Date(1447261200000)/","Type":"Payment"}]
在视图中,我使用以下代码显示它:
<tbody data-bind="foreach: AccountStatements, visible: AccountStatements().length > 0">
<tr>
<td data-bind="attr: { id: AccountStatementID }">
<a href="#" class="btn btn-primary btn-xs" data-bind="click: $root.edit"><i class="glyphicon glyphicon-pencil"></i></a>
<a href="#" class="btn btn-danger btn-xs" data-bind="click: $root.delete"><i class="glyphicon glyphicon-remove"></i></a>
</td>
<td data-bind="text: Description"></td>
<td data-bind="text: Amount"></td>
<td data-bind="date: ReceiptDate"></td>
</tr>
</tbody>
以下是格式化日期的代码:
ko.bindingHandlers.date = {
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var valueUnwrapped = ko.utils.unwrapObservable(valueAccessor());
var textContent = moment(valueUnwrapped).format("DD/MM/YYYY");
ko.bindingHandlers.text.update(element, function () { return textContent; });
}
};
在此步骤中,日期以正确的格式显示,如果我单击编辑按钮,则文本框中的ReceiptDate不会格式化。
ReceiptDate TextBox的代码:
<input type="text" placeholder="Enter Receipt Date" class="form-control fdatepicker" readonly="readonly" data-bind="value: AccountStatement().ReceiptDate" />
如果我更改为data-bind="date: AccountStatement().ReceiptDate"
,则文本框将为空。
如何格式化文本框中的日期?
更新
我已更改日期绑定处理程序,如此link,但ReceiptDate的TextBox值仍为/Date(1447261200000)/
视图中的更改:
<input type="text" placeholder="Enter Receipt Date" class="form-control fdatepicker" readonly="readonly" data-bind="date: AccountStatement().ReceiptDate" />
表中收到的日期变为空:
<td data-bind="date: ReceiptDate"></td>
答案 0 :(得分:1)
进行自定义招标是一种过度杀伤力。您的自定义绑定没有做任何值得自定义绑定的事情。
您需要的只是一个计算的observable,它返回当前日期的文本格式。
假设你在某个地方有这个变量:
var myDate = ko.observable();
在某个地方你有代码可以在其中添加一些日期对象:
myDate( input ); // where input is some date object you got somehow from somewhere
现在你只需要这个:
myDate.formatted = ko.pureComputed(function() {
return moment(myDate()).format("DD/MM/YYYY");
});
现在你可以使用普通的文本绑定:
(假设视图模型中有myDate
绑定到此视图)
<td data-bind="text: myDate.formatted"></td>
注:
myDate.formatted
没有什么特别之处。如果您考虑一下,myDate
只是一个函数,函数是对象,因此您可以将任意字段附加到它们。
创建一个像这样的新变量真的没有什么不同:
var myFormattedDate = ko.pureComputed(function() {
return moment(myDate()).format("DD/MM/YYYY");
});
在绑定中使用它:
<td data-bind="text: myFormattedDate"></td>
答案 1 :(得分:0)
在您的更新中,$root.ReceiptDate
不存在。 ReceiptDate
是AccountStatement数据的成员。跟踪上下文的级别非常重要。
您的date
绑定会设置value
,因此您无法将其用于需要text
绑定的内容(例如更新示例中的td
)。
您不需要绑定,只需要一个格式化功能,您可以在您选择的任何绑定中使用它。如果您希望能够编辑该值,则应根据日期值生成writable computed并在value
绑定中使用该值。我不在这里证明。
ajaxData = [{
"AccountStatementID": 2,
"CompanyID": 1,
"Description": "test",
"Amount": 1000,
"ReceiptDate": "/Date(1447261200000)/",
"Type": "Payment"
}];
vm = {
AccountStatements: ko.observableArray(ajaxData),
formatDate: function(textValue) {
return moment(textValue).format("DD/MM/YYYY");
}
};
ko.applyBindings(vm);
// Add a row
setTimeout(function() {
vm.AccountStatements.push({
"AccountStatementID": 2,
"CompanyID": 1,
"Description": "test",
"Amount": 1000,
"ReceiptDate": "/Date(1448271200000)/",
"Type": "Payment"
})
}, 2500);
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<table border=1>
<tbody data-bind="foreach: AccountStatements, visible: AccountStatements().length > 0">
<tr>
<td data-bind="attr: { id: AccountStatementID }"> <a href="#" class="btn btn-primary btn-xs" data-bind="click: $root.edit"><i class="glyphicon glyphicon-pencil"></i></a>
<a href="#" class="btn btn-danger btn-xs" data-bind="click: $root.delete"><i class="glyphicon glyphicon-remove"></i></a>
</td>
<td data-bind="text: Description"></td>
<td data-bind="text: Amount"></td>
<td data-bind="text: $parent.formatDate(ReceiptDate)"></td>
<td>
<input type="text" class="form-control fdatepicker" readonly="readonly" data-bind="value: $parent.formatDate(ReceiptDate)" />
</td>
</tr>
</tbody>
</table>