使用Knockoutjs的绑定日期

时间:2015-11-13 06:59:40

标签: javascript knockout.js momentjs

使用knockout将日期值绑定到文本框时出现问题,如下图所示 enter image description here

首次加载页面时,我使用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>

2 个答案:

答案 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>

相关问题