How to group and read an array using knockout.js data binding: with
I am trying to group an array
[{ "Name": "test1", "Other": "Junk" },
{ "Name": "test1", "Other": "Junk2" },
{ "Name": "test2", "Other": "Pile" }]
I am using the following method to group by attributes.
var groupBy = function (xs, key) {
return xs.reduce(function (rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
My output is, "test1": {children info}, "test2": {one child info}
I am using Knockout.js to pass this information to a modal, I am using data-bind="with: results"
I'm just not sure how to display the result as
test1 - (2) count/length of *test1 test2 - (1) count/length of *test2
I've tried using data-bind="foreach: $parent" and that doesn't seem to work. I also tried setting the object as a parent called UnpackedItems and then using foreach on the UnpackedItems.. that didn't work either.
<div class="modal fade" id="myModal" data-bind="with: TheseUnpackedItems" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Unpacked Items</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<table style="margin: auto;" class="table">
<tbody data-bind="foreach: UnpackedItems">
<tr>
<td>
<p class="form-control-static" data-bind="text: Name"></p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
self.ShowUnpacked = function(vm) {
var groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
const Property = "Name";
const GroupedUnpackedItems = groupBy(vm.UnpackedItems, Property);
var test = JSON.stringify(GroupedUnpackedItems);
var m = { "UnpackedItems": GroupedUnpackedItems }
self.TheseUnpackedItems(vm);
}
I don't get any errors, however, no data is actually displayed.
UnpackedItems
is an object. So, you can't use foreach
bindings. You can loop over the keys of the object usingObject.keys()
<tbody data-bind="foreach: Object.keys(UnpackedItems)">
<tr>
<td>
<p class="form-control-static" data-bind="text: $data"></p>
</td>
</tr>
</tbody>
Here is a working snippet:
const groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
function viewModel() {
const self = this;
const UnpackedItems=[{Name:"test1",Other:"Junk"},{Name:"test1",Other:"Junk2"},{Name:"test2",Other:"Pile"}],
Property = "Name",
GroupedUnpackedItems = groupBy(UnpackedItems, Property),
m = { "UnpackedItems": GroupedUnpackedItems }
self.TheseUnpackedItems = ko.observable(m);
}
ko.applyBindings(new viewModel)
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div id="myModal" data-bind="with: TheseUnpackedItems">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Unpacked Items</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<table style="margin: auto;" class="table">
<tbody data-bind="foreach: Object.keys(UnpackedItems)">
<tr>
<td>
<p class="form-control-static" data-bind="text: $data"></p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>