Set table columns dynamically from ko.observableArray

knockout-mvc, knockout.js

Solution

You can do that :

JS :

var VM = function () {
    var self = this;
    self.items = ko.observableArray();
    self.columnNames = ko.computed(function () {
        if (self.items().length === 0)
            return [];
        var props = [];
        var obj = self.items()[0];
        for (var name in obj)
            props.push(name);
        return props;


    });

};
var vm = new VM();

ko.applyBindings(vm);

vm.items.push({
    'Name': 'John',
    'Age': 25
});
vm.items.push({
    'Name': 'Morgan',
    'Age': 26
});

View :

<table>
    <thead>
        <tr data-bind="foreach: columnNames">
            <th> <span data-bind="text: $data"></span>

            </th>
        </tr>
    </thead>
    <tbody data-bind="foreach: items">
        <tr data-bind="foreach: $parent.columnNames">
            <td data-bind="text: $parent[$data]"></td>
        </tr>
    </tbody>
</table>

See fiddle

I hope it helps.

Problem

I am trying to output a table of data based on a `ko.observableArray` where the columns that are returned are not pre-determined. A sample of an item from my observableArray `self.userData()[0]` would be: ``` Object { RowNum: 1, ID: "123", Surname: "Bloggs", Forename: "Joe", Address line 1: "1 Park Lane" } ``` These columns would be different each time based on what the user has selected to output. I want the column headings in my output to be determined by what is present in the array, so my desired output would be: ``` <table> <thead> <tr> <th>RowNum</th> <th>ID</th> <th>Surname</th> <th>Forename</th> <th>Address line 1</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>123</td> <td>Bloggs</td> <td>Joe</td> <td>1 Park Lane</td> </tr> <!-- repeated for each row --> </tbody> </table> ``` I know I can use `foreach` to repeat rows and columns but I'm unsure how to reference it dynamically based on what is present in my `observableArray`. At the moment I have this basic structure: ``` <table> <thead> <tr data-bind="foreach: userData [property name] "> <th> <span data-bind="text: [property name]"></span> </th> </tr> </thead> <tbody data-bind="foreach: userData"> <tr data-bind="foreach: userData [property name]> <td data-bind="text: [property value]"> </td> </tr> </tbody> </table> ```

Original source