使用Knockout.js将带有嵌套数组的JS对象扁平化为单个HTML表行
Flattening JS objects with nested arrays into a single HTML table row with 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...
]
物品的type
是任意的,每次付款都可能不同。
现在我想将数组中的每笔付款显示为表中的一行。但是,我希望items数组的元素在同一行上平展,这样表看起来就像
| Date | Amount | Fee | Service | Status |
|------------|--------|-------|---------|--------|
| 10/13/2013 | 202.12 | 12.02 | 190.00 | Paid |
|------------|--------|-------|---------|--------|
| So on and so forth .... |
我使用knockout.js来生成这些表,但我无法弄清楚如何使用foreach
绑定将对象平放成一行。
将每个项目type
转换为支付对象的属性,如
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;
可以工作,但是,我事先不知道项目类型,因此不能绑定每个表单元格的text
。
有什么建议吗?
首先在支付视图模型对象上为每个已知类型创建一个ko.computed
。我
var PaymentType = function (data) {
var self = this;
self.type = ko.observable(data.type || '');
self.amount = ko.observable(data.amount || 0);
return self;
};
var Payment = function (data) {
var self = this;
self.types = ko.observableArray();
self.amount = ko.observable(data.amoumt || 0);
self.date = ko.observable(data.date || '');
self.status = ko.observable(data.status || '');
self.service = ko.computed(function () {
var paymentType = ko.utils.arrayFirst(self.types(), function (item) {
return item.type() === 'Service';
});
if (paymentType) {
return paymentType.amount();
}
return 0;
});
self.fee = ko.computed(function () {
var paymentType = ko.utils.arrayFirst(self.types(), function (item) {
return item.type() === 'Fee';
});
if (paymentType) {
return paymentType.amount();
}
return 0;
});
ko.utils.arrayForEach(data.items, function (item) {
self.types.push(new PaymentType(item));
});
return self;
};
var vm = function () {
var self = this;
self.payments = ko.observableArray();
ko.utils.arrayForEach(data, function (item) {
self.payments.push(new Payment(item));
});
return self;
};
ko.applyBindings(new vm());
则可以引用Payment中的每个字段,它应该返回一个金额或一个0。
JSFiddle演示
这样做的一种方法是在数组中跟踪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;
};
在下面的html标记中,我使用foreach绑定到Header和每个表行的allPaymentTypes数组,为每个动态支付类型动态创建th和td元素。
<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>
JSFiddle Demo
JSFiddle演示可观察属性和集合
仅供参考,我抄袭/改进了Nathan Fisher的文章
相关文章:
- 在requirejs中共享实例化对象
- 如何使用angularjs序列化对象
- 通过iron-ajax初始化对象数组(链接到caller's元素的响应)
- 有了字段的名称,我如何用空白数据初始化对象的未定义字段
- 在 Typescript 中实例化对象,遵循松散耦合
- JavaScript 数组使用 if 语句扁平化
- JSON.stringify没有序列化对象
- 如何在JavaScript中序列化对象
- 在fabric.js中初始化对象创建的子类
- 用javascript在实例方法中实例化对象
- ThreeJS:实例化对象会将其位置设置为零
- 如何:从javascript反序列化C#对象
- 使用 LoDash 或类似方法规范化/扁平化 JS 数组
- 扁平化_非常_嵌套密集型函数:如何
- 扁平化嵌套的可观察对象
- 如何扁平化多维数组包含对象在javascript
- 将对象扁平化为数组
- lodash或vanilla JS是否有很好的方法将数组对象扁平化为数组?
- UnderscoreJs:扁平化对象数组
- js扁平化对象结构与子键值对数组