【问题标题】:Binding Date using Knockoutjs使用 Knockoutjs 绑定日期
【发布时间】:2016-02-14 17:16:03
【问题描述】:

我在使用敲除将日期值绑定到文本框时遇到问题,如下图所示

第一次加载页面时,我使用 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 文本框代码:

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

【问题讨论】:

  • 类似 jsfiddle.net/LkqTU/27696 的东西。欢呼
  • @supercool 感谢您的链接,但它不起作用。在上面的链接中,您使用了通用日期格式 (dd/mm/yyyy),而在我的情况下,日期值是 json 日期格式 /Date(1447261200000)/。我已经编辑了我的问题以提供更多信息。
  • 尝试设置self.ReceiptDate=ko.observable(1447261200000);并检查它,它仍然可以工作。时刻将解码为您指定的日期和格式。
  • 哇,这些是您所做的一些重大修改。据我所知,我已删除我的答案,因为编辑使其无效。
  • @supercool 是的,它仍然可以工作jsfiddle.net/LkqTU/27697,但在我的代码中它不起作用。您能看到问题中的更新部分吗?

标签: javascript knockout.js momentjs


【解决方案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>

【讨论】:

  • 这在抽象成扩展器时更容易:ko.extenders.formattedDate = function () { ... },然后用作myDate.extend({formattedDate: "DD/MM/YYYY"})。明显的优势是可重用性,绑定可以保持不变。
  • 不行,表格中的日期没有出现,这里是链接jsfiddle.net/qdh9jw94/6。实际上,问题是在编辑模式下如何将日期绑定到 ReceiptDate 文本框(通过单击编辑按钮)
【解决方案2】:

在您的更新中,$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>

【讨论】:

  • 我尝试使用可写计算,但仍然无法正常工作。问题是当您单击编辑按钮时,日期(在文本框中)未格式化并且日历日​​期选择器未出现。 jsfiddle.net/qdh9jw94/5
  • 您将输入标记为readonly,仅此而已。您的日期选择器可能需要自定义绑定处理程序。 stackoverflow.com/questions/13629910/…你可能需要问一个新问题。
  • @Willy 你的编辑函数从你分配给AccountStatements的解包data接收它的accountStatement数据。
猜你喜欢
  • 2012-03-22
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 2013-06-24
  • 2015-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多