Set table columns dynamically from ko.observableArray
Asked Answered
H

1

7

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>
Historied answered 3/7, 2013 at 11:18 Comment(2)
Can I ask why you're not using KoGrid?Lox
@Lox Quite new to knockout, but I'll take a look at it now, thanks.Historied
I
17

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.

Ingaingaberg answered 3/7, 2013 at 11:55 Comment(7)
Hi Damien, this worked great for me, however i need to also add a filter row which will have text inputs and these would need to be bound to my view model so that when i refresh the data it will pick up any filters applied. I have tried a few things but cant get it to work, any thoughts?Spark
@Mingo, you should create a question and don't forget to add what you tried :)Ingaingaberg
of course - have created created question hereSpark
Epic! Saved me so much time figuring this out myself.Preachy
Upvoted, was doubting whether this is possible with KO, but since it is, I can use some of your fiddle sample. Appreciate it, thanks.Methacrylate
This is great, but, my column model features custom HTML (and custom knockout bindings) per TD cell. I got everything to render using template:{nodes:ColumnModel.getRowNodes()} binding. But, if the user changes the column order around, this binding doesn't fire. My new question for this is hereLomax
@Ingaingaberg I also have req of creating dynamic columns but its b/w 2 existing static columns and adding textbox on each of the columns so that the user can enter values. I have created my post at : #49433544 . Would appreciate if you can look into it as I am not getting any working examples. Thanks.Charactery

© 2022 - 2024 — McMap. All rights reserved.