fluidddynamics
fluidddynamics

Reputation: 117

Fixed First Column with Bootstrap Responsive Tables and AngularJS

I've been struggling with this CSS issue all morning, but I can't seem to make any progress.

Basically, I've got a horizontally scrolling table for which I've used Bootstrap Responsive Tables, and just removed the media-query so it scrolls horizontally at all screen sizes. I'm using Angular's ng-repeat to loop over arrays of headings and data applying to those headings, and I want the first column to stick. My HTML is as follows:

<div id="table" class="table-responsive">
        <table class="table table-bordered">
          <tr>
            <th ng-repeat="header in tableHeaders" ng-show="header.show" ng-class="'column-' + $index">
          <a ng-click="sortThis(header.name, $index)">
            <span class="glyphicon glyphicon-chevron-down" aria-hidden="true" ng-show="sortParam !== header.name"></span>
            <span class="glyphicon glyphicon-chevron-" aria-hidden="true" ng-show="sortParam === header.name"></span>
          </a> {{header.name}} 
          <span ng-show="!$first">
            <a ng-click="toggleColumn(header, $index)">X</a>
          </span>
        </th>
      </tr>
      <tr ng-repeat="row in tableData track by $index">
        <td ng-repeat="point in row | orderObjectBy:tableSort track by $index" ng-show="point.show" ng-class="'column-' + $index">{{point.name}}</td>
      </tr>
    </table>
  </div>

I have the table scrolling horizontally, and I want to freeze the first column. Right now, each column has its own class if that helps. Any ideas?

Upvotes: 3

Views: 10165

Answers (1)

g45rg34d
g45rg34d

Reputation: 9660

Here's a directive for you:

/*
This directive will fix the first column in place and will use `overflow-x:auto` for the subsequent columns.

Example use:

```
<div fixed-first-column>
    <table class="table">
        <tbody>
            <tr>
                <td><div>Row 1</div></td>
                <td>Value 1</td>
                <td>Value 2</td>
            </tr>
            <tr>
                <td><div>Row 2</div></td>
                <td>Value 1</td>
                <td>Value 2</td>
            </tr>
        </tbody>
    </table>
</div>
```
 */
app.ng.directive("fixedFirstColumn", [function () {
    return {
        restrict: "A",
        template: "<div class='table-responsive'><div ng-transclude></div></div>",
        transclude: true,
        link: function ($scope, $element) {
            var interval = setInterval(function () {
                var tr = $element.find("tr");

                angular.forEach(tr, function (i) {
                    var columns = angular.element(i).children();

                    if (columns.length < 1) {
                        // Row with no columns? Ignore it.
                        return;
                    }

                    var column0 = angular.element(columns[0]).children()[0] || columns[0];
                    var column1 = columns[1];

                    // Calculate heights of each <td>.
                    var height0 = (column0).offsetHeight;
                    var height1 = column1 ? column1.offsetHeight : 0;

                    // Calculate final height.
                    var height = Math.max(height0, height1);

                    // Set heights of <td> and <tr>.
                    columns[0].style.height = height + "px";
                    i.style.height = height + "px";

                    if (column1) {
                        column1.style.height = height + "px";
                    }

                    // If <td> heights have stabilized.
                    if (height0 !== 0 && height0 === height1) {
                        clearInterval(interval);
                    }
                });
            }, 1000);
        }
    };
}]);

See the JsFiddle for demo.

Upvotes: 2

Related Questions