【问题标题】:Knockout automapped array with formatted (computed?) column具有格式化(计算?)列的淘汰赛自动映射数组
【发布时间】:2013-03-23 21:27:17
【问题描述】:

我有一个使用 Knockout 的 CRUD 单页,一切正常,我从 JSON 调用中获取数据,它用对象列表填充了一个自动映射的可观察数组。 我可以在该数组中添加或编辑单个项目。

问题在于格式化我在表格中显示的带有对象列表的货币(数字)列。我尝试过在很多方面使用 js 函数,但是当我更新项目时,表格的格式化货币金额不会更新。 如果我使用绑定来格式化字段,则无法编辑它,因为它会转换为字符串。

我需要一个用于货币列的单向绑定(自动更新)格式列。但我无法立即创建计算列,因为我使用的是自动映射的对象数组。我尝试使用http://knockoutjs.com/documentation/plugins-mapping.html 中的示例添加计算,但我不知道如何将它与映射数组一起使用。

我的视图模型是这样的:

//--Accounts - Viewmodel Knockout
function accountViewModel() {
    var self = this;
    self.accounts = ko.observableArray();  //this is the list of objects
    self.account = ko.observable();  //single item for creating or editing

    //--get list------
    self.getAccounts = function () {
        $.postJSON(appURL + 'Accounts/GetList', function (data) {  
            ko.mapping.fromJS(data.Records, {}, self.accounts);

        });

    };

    self.getAccounts();
}   

每个帐户项目都有如下字段: -ID -姓名 -Balance

在页面中使用:

<table data-bind="visible: accounts().length > 0">
<thead>
    <tr>
        <th scope="col">Id</th>
        <th scope="col">Name</th>
        <th scope="col">Balance</th>
    </tr>
</thead>
<tbody id="accounts" data-bind="foreach: accounts">
<tr>
    <td><span data-bind="text: Id"></span></td>
    <td><a href="" data-bind="text: Name,  click: $root.getdetails" style="display:block;"></a></td>
    <td style="text-align:right;">
        <span data-bind="text: formatCurrency(Balance), css: { negative: Balance() < 0, positive: Balance() > 0 }"></span>

    </td>
</tr>
</tbody>
</table>

formatCurrency 只是一个用于格式化数字的js函数:

formatCurrency = function (value) {
    debugger;
    if (value!=undefined)
        return "$" + withCommas(value().toFixed(2));
    //had to use value() instead of value, because of toFixed
}

谢谢!

【问题讨论】:

标签: asp.net-mvc knockout.js crud knockout-mapping-plugin


【解决方案1】:

当您将文本设置为函数 (text: formatCurrency(Balance)) 的返回值时,它只运行一次。它不是可观察的,因此它的值永远不会再更新。你需要的是一个真正的蓝色计算 observable。为此,您必须自定义映射。因此,只需为您的个人帐户对象创建一个视图模型,然后将您返回的数据映射到该模型上。

var SingleAccountViewModel = function (account) {
    var model = ko.mapping.fromJS(account);

    model.FormattedBalance = ko.computed(function () {
        return formattedCurrency(model.Balance);
    });

    return model;
}

然后,当您从 AJAX 响应中取回数据时:

$.postJSON(appURL + 'Accounts/GetList', function (data) {  
    self.accounts($.map(data.Records, SingleAccountViewModel));
});

jQuery.map 方法将遍历数组并返回一个由所传递函数的返回值组成的新数组。在这种情况下,这就是您的视图模型,它现在将计算出一个 FormattedBalance,您可以绑定到它。

【讨论】:

  • 刚刚实现,现在我在我的模型中得到了计算列。但是 FormattedBalance 在更新 Balance 时仍然不会更新
  • 这是将 foreach 与 observableArray 一起使用的问题。只有对数组本身的更改才会触发更新,不会对数组in 中的对象进行更改。因此,您必须触发对数组的更改以强制更新值。懒惰的做法是简单地获取然后设置 observableArray 的值,这将更新整个块。这个 SO question 有一个更巧妙的方法:stackoverflow.com/questions/8861106/…
  • 抱歉,在实现了计算列之后,我没有注意到我在修改 Balance 字段后又收到了一个错误。出于某种原因,Knockout 将其转换为字符串,因此我在 formatCurrency 函数中得到了“对象没有方法 toFixed”。我通过将值显式转换为浮点数来解决这个问题。现在它起作用了!谢谢!
猜你喜欢
  • 2012-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-05
相关资源
最近更新 更多