Click here to Skip to main content
Click here to Skip to main content

Knockout Data-binding to Table with rowspan

, 15 Jun 2014
Rate this:
Please Sign up or sign in to vote.
Knockout Data-binding to Table with rowspan

Introduction

Using foreach data binding in knockout, we can easily bind data to a table. But the trike part comes when we need to use rowspan in table. An example could be as simple as below or could be even more complex one, when we are using rowspans to make data more presentable to the user.

Background

To accomplish our goal, we are going to use:

  1. Regular foreach data binding
  2. Container less data binding to bind additional data
  3. attr data binding to specify the rowspan

Using the Code

For a quick preview, checkout http://jsfiddle.net/y8Gzt/.

Let’s specify some models which we are going to use in the model binding.

/*Models*/
function Subject(name, mark) {
    this.name = name;
    this.mark = parseFloat(mark).toFixed(2);       
}

function Student(name, regNo, subjects) {
    this.name = name;
    this.regNo = regNo;
    this.subjects = subjects;
    this.totalMark = function() {
        var total = parseFloat(0);
        $.each(subjects, function(i) {
            total += parseFloat(subjects[i].mark);
        });
        return parseFloat(total).toFixed(2);
    };
    this.average = function() {
        var avg = this.totalMark() / parseFloat(subjects.length);
        return parseFloat(avg).toFixed(2);
    };
    this.rowSpan = subjects.length + 1;             // + 1 is important
}

Here is our view model where self.init() is populating the binding data.

/*View Model*/
function ViewModel() {
    var self = this;
    self.students = ko.observableArray([]);

    self.init = function () {
        var subjects = [
            new Subject('Math', 50),
            new Subject('Physics', 50),
            new Subject('Chemistry', 50)
        ];
        var students = [
            new Student('Alan', 'Std-01', subjects),
            new Student('Scott', 'Std-01', subjects),
            new Student('John', 'Std-01', subjects)
        ];
        self.students(students);
    };
}

Finally, we are going to apply binding for the view model:

/*binding view model*/
$(document).ready(function() {
    var vm = new ViewModel();
    vm.init();            //populates the binding data
    ko.applyBindings(vm);
});

Now let’s hook this view model to HTML table.

  1. <tbody data-bind="foreach: students"> - is just the regular binding
  2. <!-- ko foreach: subjects --> <!-- /ko --> - is the important container less binding for row murching
  3. attr: { rowspan: rowSpan } - is the rowspan binding to use rowspan in the table
<table>
    <thead>
        <tr>
            <th>Student Name</th>
            <th>Student Reg No.</th>
            <th>Subject Name</th>
            <th>Obtained Marks</th>
            <th>Total Marks</th>
            <th>Average Marks</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: students">
        <tr>
            <td data-bind="text: name, attr: { rowspan: rowSpan }"></td>
            <td data-bind="text: regNo, attr: { rowspan: rowSpan }"></td>
            <!--important to user class hidden to hide the cell-->
            <td class="hidden"></td>         
            <td class="hidden"></td>
            <td data-bind="text: totalMark(), attr: { rowspan: rowSpan }"></td>
            <td data-bind="text: average(), attr: { rowspan: rowSpan }"></td>
        </tr>

        <!--knockout Containerless Binding-->
        <!-- ko foreach: subjects -->               
        <tr>
            <!--important to user class hiddenTop to hide top border-->
            <td class="hiddenTop" data-bind="text: name"></td>
            <td class="hiddenTop" data-bind="text: mark"></td>
        </tr>
        <!-- /ko -->
    </tbody>
</table>

Now in the header section, let’s specify some styles so that our table may have a fresh and clean look. Here are some styles that are really important to use:

  1. td.hidden - hides unnecessary cells
  2. td.hiddenTop - hides unnecessary top border from cells
<style>
    table {
        border: 1px solid black;
        border-collapse: collapse;
        width: 700px;
    }
    thead {
        font-size: 15px;
        font-weight: bold
    }
    tbody {
        font-size: 15px;
        font-weight: normal
    }
    td, th {
        border: 1px solid black;
        text-align: center;
        padding: 10px;
    }
    td.hidden {
        border-width: 0px;
        padding: 0px;
    }
    td.hiddenTop {
        border-top-width: 0px;
    }
</style>

Find the VS 2010 solution in the attachment.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

diponsust

Bangladesh Bangladesh
No Biography provided

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 15 Jun 2014
Article Copyright 2014 by diponsust
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid