How to databind nested tables with filters using knockout.js?

Member

by orpha , in category: Javascript , 9 days ago

How to databind nested tables with filters using knockout.js?

Facebook Twitter LinkedIn Telegram Whatsapp

1 answer

by arnoldo.moen , 7 days ago

@orpha 

To data bind nested tables with filters using Knockout.js, you can use the following steps:

  1. Define your main view model that contains an observable array of objects, each representing a row in your main table. Each row object should also contain another observable array of objects, representing the nested rows in the nested table.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
function MainViewModel() {
    var self = this;
    
    self.rows = ko.observableArray([
        { 
            name: "Row 1", 
            nestedRows: [{ name: "Nested Row 1" }, { name: "Nested Row 2" }]
        },
        {
            name: "Row 2",
            nestedRows: [{ name: "Nested Row 3" }, { name: "Nested Row 4" }]
        }
    ]);
}


  1. Create your HTML markup for the main table and nested tables using the Knockout.js foreach binding to iterate over the rows and nested rows.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<table>
    <thead>
        <tr>
            <th>Main Table</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: rows">
        <tr>
            <td data-bind="text: name"></td>
        </tr>
        <tr>
            <td>
                <table>
                    <thead>
                        <tr>
                            <th>Nested Table</th>
                        </tr>
                    </thead>
                    <tbody data-bind="foreach: nestedRows">
                        <tr>
                            <td data-bind="text: name"></td>
                        </tr>
                    </tbody>
                </table>
            </td>
        </tr>
    </tbody>
</table>


  1. Add filtering functionality to your view model by adding an observable property for the filter text and a computed property to filter the rows based on the filter text.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function MainViewModel() {
    var self = this;
    
    self.rows = ko.observableArray([
        { 
            name: "Row 1", 
            nestedRows: [{ name: "Nested Row 1" }, { name: "Nested Row 2" }]
        },
        {
            name: "Row 2",
            nestedRows: [{ name: "Nested Row 3" }, { name: "Nested Row 4" }]
        }
    ]);
    
    self.filterText = ko.observable("");
    
    self.filteredRows = ko.computed(function() {
        var filter = self.filterText().toLowerCase();
        return ko.utils.arrayFilter(self.rows(), function(row) {
            return row.name.toLowerCase().indexOf(filter) >= 0 ||
                ko.utils.arrayFirst(row.nestedRows(), function(nestedRow) {
                    return nestedRow.name.toLowerCase().indexOf(filter) >= 0;
                });
        });
    });
}


  1. Update your HTML markup to bind the filter input to the filterText property and use the filteredRows computed property instead of the rows observable array.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<input type="text" data-bind="value: filterText, valueUpdate: 'input'">

<table>
    <thead>
        <tr>
            <th>Main Table</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: filteredRows">
        <tr>
            <td data-bind="text: name"></td>
        </tr>
        <tr>
            <td>
                <table>
                    <thead>
                        <tr>
                            <th>Nested Table</th>
                        </tr>
                    </thead>
                    <tbody data-bind="foreach: nestedRows">
                        <tr>
                            <td data-bind="text: name"></td>
                        </tr>
                    </tbody>
                </table>
            </td>
        </tr>
    </tbody>
</table>


By following these steps, you can databind nested tables with filters using Knockout.js in your web application.