Sticky Angular Headers

I am struggling to create a table on my angular page that has fixed headers and footers.

<table class="table table-bordered table-striped table-hover" fixed-header>
  <thead>
      <tr>
          <th>Name</th>
          <th>Amount</th>
          <th>Id</th>
      </tr>
  </thead>
  <tbody>
      <tr class="info" ng-repeat="item in ctrl.items track by $index">
          <td>
              <input type="checkbox"/>
              <a>{{item.displayName}}</a>
          </td>
          <td>
              {{item.marketValue}}
          </td>
          <td>
              {{item.positions}}
          </td>
      </tr>
  </tbody>
  <tfoot>
      <tr>
          <td>Name</td>
          <td>Amount</td>
          <td>Id</td>
      </tr>
  </tfoot>
</table>

You can view a demo of my angular table here on plunker. I have been using the angu-fixed-header-table plugin, but unfortunately, the table is not displaying fixed headers. Any suggestions on how to resolve this issue?

Answer №1

It seems that the table-height attribute is missing. To see a working demonstration, please visit this link: https://plnkr.co/edit/BdiQzYxVyPdFXU9TI44t?p=preview

/**
 * Custom AngularJS directive for fixed header scrollable tables
 * @version 1.2.0
 */
(function () {
    angular
        .module('anguFixedHeaderTable', [])
        .directive('fixedHeader', fixedHeader);

    fixedHeader.$inject = ['$timeout'];

    function fixedHeader($timeout) {
        return {
            restrict: 'A',
            link: link
        };

        function link($scope, $elem, $attrs, $ctrl) {
            var elem = $elem[0];

            // Wait for data to load and then transform the table
            $scope.$watch(tableDataLoaded, function(isTableDataLoaded) {
                if (isTableDataLoaded) {
                    transformTable();
                }
            });

            function tableDataLoaded() {
                // The first cell in the tbody exists when data is loaded but doesn't have a width
                // until after the table is transformed
                var firstCell = elem.querySelector('tbody tr:first-child td:first-child');
                return firstCell && !firstCell.style.width;
            }

            function transformTable() {
                // Reset display styles so column widths are correct when measured below
                angular.element(elem.querySelectorAll('thead, tbody, tfoot')).css('display', '');

                // Wrap in $timeout to give table a chance to finish rendering
                $timeout(function () {
                    // Set widths of columns
                    angular.forEach(elem.querySelectorAll('tr:first-child th'), function (thElem, i) {

                        var tdElems = elem.querySelector('tbody tr:first-child td:nth-child(' + (i + 1) + ')');
                        var tfElems = elem.querySelector('tfoot tr:first-child td:nth-child(' + (i + 1) + ')');

                        var columnWidth = tdElems ? tdElems.offsetWidth : thElem.offsetWidth;
                        if (tdElems) {
                            tdElems.style.width = columnWidth + 'px';
                        }
                        if (thElem) {
                            thElem.style.width = columnWidth + 'px';
                        }
                        if (tfElems) {
                            tfElems.style.width = columnWidth + 'px';
                        }
                    });

                    // Set CSS styles on thead and tbody
                    angular.element(elem.querySelectorAll('thead, tfoot')).css('display', 'block');

                    angular.element(elem.querySelectorAll('tbody')).css({
                        'display': 'block',
                        'height': $attrs.tableHeight || 'inherit',
                        'overflow': 'auto'
                    });

                    // Reduce width of last column by the width of the scrollbar
                    var tbody = elem.querySelector('tbody');
                    var scrollBarWidth = tbody.offsetWidth - tbody.clientWidth;
                    if (scrollBarWidth > 0) {
                        // For some reason, trimming the width by 2px lines everything up better
                        scrollBarWidth -= 2;
                        var lastColumn = elem.querySelector('tbody tr:first-child td:last-child');
                        lastColumn.style.width = (lastColumn.offsetWidth - scrollBarWidth) + 'px';
                    }
                });
            }
        }
    }
})();

var app = angular.module('myApp', ['anguFixedHeaderTable'])
.controller('DemoController', function($scope) {
    $scope.products = [
      {
        displayName: 'Prod1',
        marketValue: '100',
        positions:'1'
      },
      ...
      // Additional product objects here
      ...
      {
        displayName: 'Prod1',
        marketValue: '100',
        positions:'1'
      },
    ];
});
<!DOCTYPE html>
<html ng-app="myApp">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script src="https://code.angularjs.org/1.4.9/angular.js" data-semver="1.4.9"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="DemoController">
<table table-height="100px" class="table table-bordered table-striped table-hover" fixed-header>
  <thead>
      <tr>
          <th>Name</th>
          <th>Amount</th>
          <th>Id</th>
      </tr>
  </thead>
  <tbody>
      <tr class="info" ng-repeat="item in products track by $index">
          <td>
              <input type="checkbox"/>
              <a>{{item.displayName}}</a>
          </td>
          <td>
              {{item.marketValue}}
          </td>
          <td>
              {{item.positions}}
          </td>
      </tr>
  </tbody>
  <tfoot>
      <tr>
          <td>Name</td>
          <td>Amount</td>
          <td>Id</td>
      </tr>
  </tfoot>
</table>
  </body>

</html>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Challenges with Internal Styling on Wordpress Sites

Okay. I've been dealing with some internal style issues on my Wordpress website. After dedicating hours to trying to change styles for various elements, I realized that the main html file contained a bunch of internal style sheets that were overridin ...

There seems to be a problem with how the navbar is being displayed in ResponsiveSlides.js

I am currently using WordPress, but I have come here seeking help with a jQuery/CSS issue. I am utilizing responsiveSlides.js to create a simple slideshow, however, when viewing it here at gallery link, it appears that something is not quite right. STEPS: ...

When I click on a tab section to expand it, the carat arrows all point upwards. Only the arrows corresponding to the selected section should

click here for imageIt appears that there are four tabs, each with a click function on the carat icon. When I expand one tab, all carats point upwards instead of only the selected one appearing. accountSelection(account) { if (!this.selectedAccoun ...

I am experiencing an issue where the CSS file is not being loaded in my HTML file while using the Netbeans IDE

I am a beginner in HTML and CSS and I have been trying to link my CSS file to my HTML code after reading various solutions on Stack Overflow. Unfortunately, I am facing difficulty as the CSS file is not loading in my HTML code. If anyone can offer assistan ...

Organizing content into individual Div containers with the help of AngularJS

As someone who is new to the world of AngularJS, I am currently in the process of learning the basics. My goal is to organize a JSON file into 4 or 5 separate parent divs based on a value within the JSON data, and then populate these divs with the correspo ...

Trouble with Bootstrap 3's nav-justified feature not displaying correctly upon window expansion

Looking at this Bootstrap example page, I noticed a small issue with the nav-justified navigation. When the window is minimized, it transitions correctly to a mobile version. However, when the window is maximized again, the buttons remain in the mobile for ...

Having trouble creating multiple PDFs with mPDF without having to store them on the server

I am creating several PDF files in a loop using the mPDF library. Here is a snippet of my code: for($i=0;$i<=3;$i++) { $mpdf = new mPDF(); $stylesheet = file_get_contents('style.css'); $mpdf->WriteHTML($stylesheet,1); $mpd ...

Begin expanding new circles in jQuery from the exact location where the previous ones ended

A captivating circle animation unfolds before your eyes, featuring dark blue circles that materialize at random points and gradually expand. As these expanding circles cover more than half of the screen, their color shifts to a lighter shade of blue. Exper ...

The align-middle Bootstrap class does not seem to be working within the specified div

I want to vertically align text (<span class="align-middle">middle</span>) in the center of a div. Here is the code snippet: <div class="col-4 shadow product-added"> <div class="row"> <div cla ...

What is the best way to position the publication date of an article at the bottom of the

I am looking to have the article publishing date (1/9/2016) positioned at the bottom inside the container. Right now, the date appears just below the text, but I want it to be aligned at the bottom of the container. The website in question is watchathletic ...

Is there a way to deactivate a button upon clicking and then substitute it with a new button that serves a different purpose in AngularJS?

Is there a way to deactivate a button once clicked and substitute it with another button that performs a different task using AngularJS? Here is the button in question: <button type="submit" class="btn btn-small btn-default" ng-disabled="isteam==0 || ...

What is the best way to assess a scope object within an ng-Class directive?

Whenever I click a button, it moves to the next item in an array. Once it reaches the last item in the array, I want to assign the "endButton" class to the button tag. I plan to use the ng-class directive within the HTML code to evaluate the expression. T ...

Unable to capture HTML form input in $_POST[]

I've encountered an unusual issue while transferring data from an email form (HTML5) to ajax/JSON and receiving false in order to prevent redirection to the php script after pressing the submit button. When I include commas between each data paramete ...

What could be causing the right padding to be overlooked next to the scroll bar, and what steps can be taken to address this

https://i.sstatic.net/0laRo.jpg .outer { padding: 50px; } .inner { width: 500px; height: 1000px; border: 1px solid gray; margin: auto; } <div class="outer"> <div class="inner"> <div class="content">qwerty</div> ...

The use of "runat="server" in the HTML Head tag is preventing C# embedded code blocks from being converted to client-side code

After I included runat="server" in the head tag and added a CSS href with the value of <%= WebAppInstance %>, I noticed that the <%= WebAppInstance %> was not being converted to client-side code. To provide clarity on my question, please refer ...

What is the right height and width to use in CSS?

I find it challenging to decide when to use rem, em, px, or % in web design. Although I know the definitions of each unit, I struggle with knowing the appropriate situations to utilize them. What guidelines should I follow to determine which one to use? ...

Use vertical gaps to separate items by applying the following technique:

One of my components is designed to act as a badge. The CSS for this component includes: https://i.sstatic.net/F0QZ6.png HTML: <div class="label label-as-badge"> {{ value.Termo }} <i class="fa fa-times"></i ...

Adding Jquery content to HTML templates using Jinja2: A Simple Guide

Looking at my HTML code Base.html <title> {% block title %}{% endblock %} </title> </head> <body> <nav class="navbar navbar-expand-lg navbar-light bg-light"> <div class="collapse na ...

Steps for implementing an <h1> element with the React Material UI theme

I have chosen the 'dark' theme and would like to apply it to an h1 element. How can I achieve this? The method below does not yield the desired result: <MuiThemeProvider theme={theme}> <h1>Page Title</h1> ... The following ...

Trouble with Angular2: Socket.io event not refreshing the view

I attempted to update my view upon receiving a socket event. This is what my component code looks like: constructor(private _zone: NgZone){ this.socket = io.connect('http://localhost:3000'); this.socket.on('someEvent', function ...