Reputation: 241
I have an observableArray
that is populated by dynamic sql data. So the columns returned could be different at any time.
I want to display the SQL results in a HTML table. However, the below is not working.
This is how I want the output to look...
var viewModel = function(data) {
var self = this;
// variables
self.taskRecordOverview = ko.observableArray([
{
"Entity": "DEMO",
"Period": "2017-07-31T00:00:00",
"Level": "Level 3",
"Addendum Errors": null,
"Cash Process": "Created",
"Corporate Actions": null,
"Expenses": null
},
{
"Entity": "DEMO",
"Period": "2017-07-31T00:00:00",
"Level": "Level 5",
"Addendum Errors": "Created",
"Cash Process": "Created",
"Corporate Actions": "Created",
"Expenses": "Created"
},
{
"Entity": "SP00",
"Period": "2017-07-31T00:00:00",
"Level": "Level 5",
"Addendum Errors": "Created",
"Cash Process": "Approved",
"Corporate Actions": "Created",
"Expenses": "Created"
}
]);
};
ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<table>
<thead>
<tr>
<th>??</th>
</tr>
</thead>
<tbody data-bind="foreach: taskRecordOverview">
<tr>
<td data-bind="text: $data"></td>
</tr>
</tbody>
</table>
https://jsfiddle.net/f79r4h2g/
Upvotes: 1
Views: 1159
Reputation: 35222
Inside your foreach
loop for taskRecordOverview
, you need to loop through the keys
of each object and display the value. You can do so with Object.keys
Working snippet:
var viewModel = function() {
var self = this;
self.taskRecordOverview = ko.observableArray([{
"Entity": "DEMO",
"Period": "2017-07-31T00:00:00",
"Level": "Level 3",
"Addendum Errors": null,
"Cash Process": "Created",
"Corporate Actions": null,
"Expenses": null
},
{
"Entity": "DEMO",
"Period": "2017-07-31T00:00:00",
"Level": "Level 5",
"Addendum Errors": "Created",
"Cash Process": "Created",
"Corporate Actions": "Created",
"Expenses": "Created"
},
{
"Entity": "SP00",
"Period": "2017-07-31T00:00:00",
"Level": "Level 5",
"Addendum Errors": "Created",
"Cash Process": "Approved",
"Corporate Actions": "Created",
"Expenses": "Created"
}
]);
};
ko.applyBindings(new viewModel());
td, th {
border: 1px solid #dddddd;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<table>
<thead>
<!--Only one object is enough for header-->
<tr data-bind="foreach:Object.keys(taskRecordOverview()[0]),visible:taskRecordOverview().length > 0">
<th data-bind="text:$data"></th>
</tr>
</thead>
<tbody data-bind="foreach: taskRecordOverview">
<!--Get the keys in each object and loop through them-->
<tr data-bind="foreach: Object.keys($data)">
<!--Get the "value" for a key-->
<td data-bind="text: $parent[$data]"></td>
</tr>
</tbody>
</table>
If the nested $data
and $parent
binding contexts are confusing then we can alias foreach items using as
to make it more clear:
<table>
<tbody data-bind="foreach: { data:taskRecordOverview, as: '_task'}">
<tr data-bind="foreach: { data:Object.keys(_task), as: '_key'}">
<td data-bind="text: _task[_key]"></td>
</tr>
</tbody>
</table>
I know this is an old question, but it is an interesting one and the answer will hopefully help someone else in the future :)
Upvotes: 1