Javascript 使用Knockoutjs绑定日期

Javascript 使用Knockoutjs绑定日期,javascript,knockout.js,momentjs,Javascript,Knockout.js,Momentjs,我在使用knockout将日期值绑定到文本框时遇到了一个问题,如下图所示 第一次加载页面时,我使用ajax获取AccountStatements数据 function AccountStatementViewModel(companyID) { var self = this; ... var AccountStatement = { AccountStatementID: self.AccountStatementID, Company

我在使用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);
    }
    ...
}
控制器以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>
在这一步中,日期以正确的格式显示,然后如果单击编辑按钮,文本框中的ReceiptDate将不格式化

ReceiptDate文本框的代码:

<input type="text" placeholder="Enter Receipt Date" class="form-control fdatepicker" readonly="readonly" data-bind="value: AccountStatement().ReceiptDate" />
表中的接收日期变为空:

<td data-bind="date: ReceiptDate"></td>

在更新中,
$root.ReceiptDate
不存在
ReceiptDate
是AccountStatement数据的成员。跟踪上下文的层次是很重要的

您的
日期
绑定将设置一个
,因此您不能将其用于需要
文本
绑定的内容(如更新示例中的
td

您不需要绑定,只需要一个格式化函数,可以在您选择的任何绑定中使用它。如果您希望能够编辑该值,那么您应该基于日期值进行编辑,并在
绑定中使用该值。我没有在这里证明这一点

ajaxData=[{
“AccountStatementID”:2,
“公司ID”:1,
“说明”:“测试”,
“金额”:1000,
“接收日期”:“/日期(1447261200000)/”,
“类型”:“付款”
}];
vm={
会计报表:ko.observableArray(ajaxData),
formatDate:函数(textValue){
返回时刻(textValue).format(“DD/MM/YYYY”);
}
};
ko.应用绑定(vm);
//添加一行
setTimeout(函数(){
vm.AccountStatements.push({
“AccountStatementID”:2,
“公司ID”:1,
“说明”:“测试”,
“金额”:1000,
“接收日期”:“/日期(1448271200000)/”,
“类型”:“付款”
})
}, 2500);

进行定制投标是一种过火的做法。您的定制绑定没有做任何值得定制绑定的事情

您所需要的只是一个返回当前日期文本格式的计算可观测值

假设您在某个地方有一个变量:

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: myFormattedDate"></td>


类似这样的内容。cheers@supercool谢谢你的链接,但它不工作。在上面的链接中,您使用了通用日期格式(dd/mm/yyyy),而在我的例子中,日期值是json日期格式
/date(1447261200000)/
。我编辑了我的问题以提供更多信息。请尝试设置
self.ReceiptDate=ko.observable(1447261200000)并检查它,它仍然可以工作。“时刻”将解码到指定的日期和格式。Wew,这些是您所做的一些主要编辑。我已经删除了我的答案,因为在我看来编辑使它无效。@supercool是的,它仍然有效,但在我的代码中它不起作用。你能看到问题中的更新部分吗?如果抽象成一个扩展程序,这就更容易了:
ko.extenders.formattedDate=function(){…}
,然后用作
myDate.extend({formattedDate:“DD/MM/yyyyy”})
。明显的优点是可重用性,绑定可以保持不变。它不起作用,表中的日期不会出现,这是链接。实际上,问题是如何在编辑模式下(通过单击编辑按钮)将日期绑定到ReceiptDate文本框。我已经尝试使用可写计算,但仍然无法工作。问题是,当您单击编辑按钮时,日期(在文本框中)未格式化,并且日历日期选择器未显示。您将输入标记为
只读
。您的日期选择器可能需要自定义绑定处理程序。您可能需要问一个新问题。@Willy您的编辑函数将从分配给
AccountStatements
的未包装
数据中接收其
accountStatement
数据。
myDate.formatted = ko.pureComputed(function() {
    return moment(myDate()).format("DD/MM/YYYY");
});
<td data-bind="text: myDate.formatted"></td>
var myFormattedDate = ko.pureComputed(function() {
    return moment(myDate()).format("DD/MM/YYYY");
});
<td data-bind="text: myFormattedDate"></td>