Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fixed header table in AngularJS

I'm stuck on a problem involving a fixed header table. I'm using AngularJS & Bootstrap to build a web application. I can't use ng-grid as it doesn't support IE7. So, I'm populating the table rows by ng-repeat. The application is responsive. So, I can't give fixed width to the cells/headers. Is there any simple way to have the table headers fixed?

I've put up a Plunker at Fixed header table with AngularJS

Thanks in advance.

like image 875
Arnab Das Avatar asked Jun 28 '13 10:06

Arnab Das


2 Answers

I created a directive for this recently, you can install it using bower:

bower install angu-fixed-header-table

For more details and a working example you can see my blog post at http://pointblankdevelopment.com.au/blog/angularjs-fixed-header-scrollable-table-directive

like image 50
Jason Watmore Avatar answered Nov 13 '22 04:11

Jason Watmore


I used Kumar's suggestion and created two tables. One contains the thead, and the other contains both the thead and the tbody.

<div ng-style="{'margin-right': scrollBarWidth}">
    <table>
       <thead>
         <tr>
            <th width="{{tableSizes[0].width}}">Col0</th>
            <th width="{{tableSizes[1].width}}">Col1</th>
            <th width="{{tableSizes[2].width}}">Col2</th>
         </tr>
       </thead>
    </table>
 </div> 
 <div class="fixedHeadBody">
    <table ng-style="{'margin-top': -rowSize.height}">
       <thead>
         <tr el-size="rowSize">
           <th el-size="{{tableSizes[0].width}}">Col0</th>
           <th el-size="{{tableSizes[1].width}}">Col1</th>
           <th el-size="{{tableSizes[2].width}}">Col2</th>
         </tr>
       </thead>
       <tbody>
         <!-- data goes here -->
       </tbody>
    </table>
 </div>

Within the thead of the second one, I added a directive (see below) that watches the width and the height of each column. The output of these columns are used to set the width of the first thead (angular binding). I also added the same directive to the thead tr of the second table, and use the height value to hide the scrollable thead of the second table. That way, I only show the first thead which is fixed.

One more thing I had to sort out was the scrollBar. The scroll bar takes space and that misalign the columns between the first and the second table. To fix this, I added a margin-right to the top table that is equal to the width of scroll bar (width difference between the div containing the table and the table). The scrollbar width varies between browsers and the last function works for any browser.

app.directive('elSize', ['$parse', '$timeout', function ($parse, $timeout) {
    return function(scope, elem, attrs) {
        var fn = $parse(attrs.elSize);

        scope.$watch(function () {
            return { width: elem.innerWidth(), height: elem.innerHeight() };
        },
        function (size) {
            fn.assign(scope, size);
        }, true);
    }
}])

Within the controller, you can set the scrollBarWidth using the function below. You can call $scope.setScrollBarWidth() from anywhere once the table has been rendered.

    $scope.scrollBarWidth = "5px";
    $scope.setScrollBarWidth = function () {
        $timeout(function () {
            var divWidth = $(".fixedHeadBody").width();
            var tableWidth = $(".fixedHeadBody table").width();
            var diff = divWidth - tableWidth;
            if (diff > 0) $scope.scrollBarWidth = diff + "px";
        }, 300);
    }
like image 41
Mutai Victor Avatar answered Nov 13 '22 03:11

Mutai Victor