Javascript 使用Knockout.JS将具有嵌套数组的JS对象展平到单个HTML表行中

Javascript 使用Knockout.JS将具有嵌套数组的JS对象展平到单个HTML表行中,javascript,html,json,knockout.js,Javascript,Html,Json,Knockout.js,我有一系列付款数据,看起来类似于: [{ amount: "$202.12", date: "10/13/2013", items: [{type: "Service", amount: "$190.00"}, {type: "Fee", amount: "12.12"}], status: "Paid" }, // More of the same... ] 项目的类型是任意的,每次付款都可能不同 现在,我想将数组中的每个付款显示为表中的一行。但是,我希望items数组的元素

我有一系列付款数据,看起来类似于:

[{
  amount: "$202.12",
  date: "10/13/2013",
  items: [{type: "Service", amount: "$190.00"}, {type: "Fee", amount: "12.12"}],
  status: "Paid"
},
// More of the same...
]
项目的
类型
是任意的,每次付款都可能不同

现在,我想将数组中的每个付款显示为表中的一行。但是,我希望items数组的元素在同一行上展平,以便表看起来像

| Date       | Amount | Fee   | Service | Status |
|------------|--------|-------|---------|--------|
| 10/13/2013 | 202.12 | 12.02 | 190.00  | Paid   |
|------------|--------|-------|---------|--------|
| So on and so forth ....                        |
我正在使用knockout.js生成这些表,但我不知道如何使用
foreach
绑定将对象展平成一行

将每个项目
类型
转换为支付对象的属性,如

var payment = {
  amount: "$202.12",
  date: "10/13/2013",
  items: [{type: "Service", amount: "$190.00"}, {type: "Fee", amount: "12.12"}],
  status: "Paid"
};
var flatPayment = {
  amount: payment.amount,
  status: payment.status,
  date: payment.date
};

for (var i = 0; i < payment.items.length; i++) 
  flatPayment[payment.items[i].type] = payment.items[i].amount;
var付款={
金额:“$202.12”,
日期:“2013年10月13日”,
项目:[{类型:“服务”,金额:$190.00},{类型:“费用”,金额:$12.12}],
状态:“已支付”
};
var flatPayment={
金额:payment.amount,
状态:payment.status,
日期:付款日期
};
对于(变量i=0;i
可以工作,但是,我事先不知道项目类型,因此无法绑定每个表单元格的
文本


有什么建议吗?

首先在payment viewmodel对象的已知类型上为每个类型创建一个
ko.computed
。 我

然后,您可以从付款中引用每个字段,它应该返回金额或0


实现这一点的一种方法是跟踪在开发时在阵列中vm根目录中未知的支付类型。然后,可以在根vm和用于绑定的付款行之间共享此阵列

在下面的代码中,我有一个名为allPaymentTypes的数组,它在vm的根目录下公开,并且在每次付款时公开

构建vm时,我通过将每个唯一的付款项目添加到allPaymentTypes数组来处理每个付款,在每个付款上创建paymentAmountLook,并添加帮助函数以查找特定付款类型的每个付款金额

var vm = function (payments) {
    var self = this;
    self.payments = payments;
    self.allPaymentTypes = [];

    ko.utils.arrayForEach(payments, processPayment);

    function processPayment(payment) {
        payment.allPaymentTypes = self.allPaymentTypes;
        payment.paymentAmountLookUp = {};

        ko.utils.arrayForEach(payment.items, function (paymentItem) {
            processPaymentItem(payment, paymentItem);
        });

        //Helper function to get the payment amount for a payment type
        //Will handle situations where a specific payment does not have a payment amount
        payment.getPaymentAmount = function (paymentType) {
            return payment.paymentAmountLookUp[paymentType] || '$0';
        };
    }

    function processPaymentItem(payment, paymentItem) {
        payment.paymentAmountLookUp[paymentItem.type] = paymentItem.amount;

        if (self.allPaymentTypes.indexOf(paymentItem.type) === -1) {
            self.allPaymentTypes.push(paymentItem.type);
        }
    }

    return self;
};
<table class="table">
    <thead>
        <tr>
            <th>Date</th>
            <th>Amount</th>
            <!-- ko foreach: allPaymentTypes -->
            <th data-bind="text: $data"></th>
            <!-- /ko -->
            <th>Status</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: payments">
        <tr>
            <td data-bind="text: date"></td>
            <td data-bind="text: amount"></td>
            <!-- ko foreach: allPaymentTypes -->
            <td data-bind="text: $parent.getPaymentAmount($data)"></td>
            <!-- /ko -->
            <td data-bind="text: status"></td>
        </tr>
    </tbody>
</table>
在下面的html标记中,我在标题和每个表行中使用对allPaymentTypes数组的foreach绑定来为每个动态支付类型动态创建th和td元素

var vm = function (payments) {
    var self = this;
    self.payments = payments;
    self.allPaymentTypes = [];

    ko.utils.arrayForEach(payments, processPayment);

    function processPayment(payment) {
        payment.allPaymentTypes = self.allPaymentTypes;
        payment.paymentAmountLookUp = {};

        ko.utils.arrayForEach(payment.items, function (paymentItem) {
            processPaymentItem(payment, paymentItem);
        });

        //Helper function to get the payment amount for a payment type
        //Will handle situations where a specific payment does not have a payment amount
        payment.getPaymentAmount = function (paymentType) {
            return payment.paymentAmountLookUp[paymentType] || '$0';
        };
    }

    function processPaymentItem(payment, paymentItem) {
        payment.paymentAmountLookUp[paymentItem.type] = paymentItem.amount;

        if (self.allPaymentTypes.indexOf(paymentItem.type) === -1) {
            self.allPaymentTypes.push(paymentItem.type);
        }
    }

    return self;
};
<table class="table">
    <thead>
        <tr>
            <th>Date</th>
            <th>Amount</th>
            <!-- ko foreach: allPaymentTypes -->
            <th data-bind="text: $data"></th>
            <!-- /ko -->
            <th>Status</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: payments">
        <tr>
            <td data-bind="text: date"></td>
            <td data-bind="text: amount"></td>
            <!-- ko foreach: allPaymentTypes -->
            <td data-bind="text: $parent.getPaymentAmount($data)"></td>
            <!-- /ko -->
            <td data-bind="text: status"></td>
        </tr>
    </tbody>
</table>

日期
数量
地位


仅供参考,我剽窃/改进了Nathan Fisher的帖子。

我不知道
结构!你的回答很有帮助。谢谢你的回答。