Coder Social home page Coder Social logo

cornflourblue / angu-fixed-header-table Goto Github PK

View Code? Open in Web Editor NEW
67.0 67.0 43.0 17 KB

AngularJS fixed header scrollable table directive

Home Page: http://pointblankdevelopment.com.au/blog/angularjs-fixed-header-scrollable-table-directive

License: MIT License

JavaScript 100.00%

angu-fixed-header-table's Introduction

About me

I'm a web developer and blogger from Sydney, you can find my blog at https://jasonwatmore.com/.

Other than coding, I'm currently attempting to travel around Australia by motorcycle with my wife Tina on a pair of Royal Enfield Himalayans, you can follow our adventure on YouTube and Instagram.

angu-fixed-header-table's People

Contributors

cornflourblue avatar jmaynier avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

angu-fixed-header-table's Issues

Not using tags

If you have registered your component with bower, you need to tag and push the tags to the repo for users to be able to target the version they want. You have no tags pushed up here.

Mixed display when updating the set of items.

In the initial page load, the table is displayed well and spans the width of the page. However, if I re-load the content via ajax, the display is not clean in that it does not take up the full page width. The body is also positioned differently from the rest of the data.
screenshot 2015-03-04 12 25 57

Is there a way to customize the height?

Love this plugin, but the height remains fixed at 400px in the tBody. Is it possible to add a scope variable to the directive so you can pass a dynamic height in?

Doesn't work under tabs

Getting Empty header with header values below header when used under "tab-pane fade" class inside "tab-content" class

Firstchild always null

There is a piece of code in angu-fixed-header-table.js

       $scope.$watch(tableDataLoaded, function(isTableDataLoaded) {
            if (isTableDataLoaded) {
                transformTable();
            }
        });

        function tableDataLoaded() {
            // 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;
        }

The problem is my firstChild is always null, and doesn't have a value. So, my table is never transformed and the directive doesn't work for me.

Fixed Column Widths Conflicts with Other CSS

In the 'transformTable()' function there is a 'for each' loop that adds a 'width' style to the table header and table data elements of the table. This causes problems if the user has other css related to the with of and elements since the fixed width style will override everything else. I'm not quite clear on what the purpose of setting the widths of those elements even is. As far as I can tell, the widths of the elements in the and are already in sync at this point and don't need any further adjustment.

Could the code that sets the fixed widths be removed or at least made optional with a flag in the attributes?

scope watch change to make it work

First of all, thanks for a great directive!

I just wanted to let you know that I had to alter the $scope.$watch function to include

 || isTableDataLoaded !== null

in the If statement. The original

if (isTableDataLoaded)

was not working...

Not supported to IE

Trying to use this directive but it is not supported to IE, is it possible to update this directive

Fixed First Column

Hi, is there a way to fix the first column (in addition to the top row)?
Thanks
Jaya

3 issues and 2 enhancements

I encountered and fixed 3 issues and made an enhancement (but didn't do a pull request because I'm actually not really used to github)

First issue : I had bootstrap datepickers in my thead. These directive create tables (to display a calendar). Angu-fixed-header-table was "fixing" this calendar's td widths instead of my table using angu-fixed-header-table.

Second issue : the scrollbar problem - I tweaked it more than fixed it : instead of reducing the size of the last td of tbody, I widened the last td of thead and tfoot. It worked better and didn't need any adjustement. The behaviour changes juste a bit, but I do believe it's better this way.

Third issue : the table's header css were refreshed only when the first cell of tbody had no width set. As a result, if I was setting it through another directive, it failed to refresh. To fix it in the most reliable way, I had to add a scope. So now, I MUST set a "table-data" attribute wich is an Array object containing all the datas displayed in my table. As a result, anytime my table-data changes, the tHead's css is recalculated.

First enhancement : before I changed it, setting the tableHeight attribute was just like fixing the table height. Now it's like setting table max-height (since max-height would be ignored otherwise). However, you now have to set the attribute like this :
<table fixed-header table-height=300>

Second enhancement : you used to change the thead / tbody / tfoot display to '' and back to 'block' every time transformTable was called. The thing is that I wanted to use your directive along with an ngInfiniteScroll directive to scroll as much a I wanted on my table and still have my headers there. Since I loaded more data in my array, my table headers had to adapt to the new column's width, thus applying the transformTable function wich changes the display -even for a split second- and made the scrollbar disappeared. The display-swap had an effect similar to forcing the user to drop the scrollbar, he had to click it again to scroll some more.
Instead of changing the display, I create a clone of elem and operate everything that was requiring the display to be back to '' on that clone. Once done, I delete the clone.
Although human eye shouldn't be able to see the clone (since I had to append the clone to the table's parent to get it's actual width, but I remove it as soon as I can), I made sure it wouldn't mess the page, even for that split second by putting the clone in a wrapper div with height set to 0 px and overflow hidden + visibility set to invisible (wich is a bit of an overkill I guess)

Anyway, here is the new code for the transformTable function in your directive :

(function () {
    angular
        .module('anguFixedHeaderTable', [])
        .directive('fixedHeader', fixedHeader);

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

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

        function link($scope, $elem, $attrs, $ctrl) 
        {
            var elem = $elem[0];
            $scope.$watch('tableData', function(newValue) 
            {
                if (Array.isArray(newValue)) 
                {
                    transformTable();
                }
            }, true);

            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 () 
                {
                    //instead of doing any calculs on elem, we will do them on a clone of him !
                    //This way we won't change the display of the table itself, thus not enabling / disabling scrolling (wich makes the cursor 'drop' the scrollbar)
                    var clone = elem.cloneNode(true);
                    var wrapper= document.createElement('div');
                    wrapper.style.height = '0px';
                    wrapper.style.overflow = 'hidden';
                    wrapper.style.visibility = 'invisible';
                    wrapper.appendChild(clone);
                    angular.element(clone.querySelectorAll('thead, tbody, tfoot')).css('display', '');
                    $elem.parent()[0].appendChild(wrapper);
                    // set widths of columns
                    angular.forEach(clone.querySelectorAll('tr:first-child th:not(:last-child)'), function (clonedThElem, i) 
                    {
                        var clonedTdElems = clone.querySelector('table[fixed-header]>tbody tr:first-child th:nth-child(' + (i + 1) + '), table[fixed-header]>tbody tr:first-child td:nth-child(' + (i + 1) + ')');
                        var columnWidth = clonedTdElems ? clonedTdElems.offsetWidth : clonedThElem.offsetWidth;
                        var tdElems = elem.querySelector('table[fixed-header]>tbody tr:first-child th:nth-child(' + (i + 1) + '), table[fixed-header]>tbody tr:first-child td:nth-child(' + (i + 1) + ')');
                        var thElems = elem.querySelector('table[fixed-header]>thead tr:first-child th:nth-child(' + (i + 1) + '), table[fixed-header]>thead tr:first-child td:nth-child(' + (i + 1) + ')');
                        var tfElems = elem.querySelector('table[fixed-header]>tfoot tr:first-child th:nth-child(' + (i + 1) + '), table[fixed-header]>tfoot tr:first-child td:nth-child(' + (i + 1) + ')');
                        if (tdElems) 
                        {
                            tdElems.style.width = columnWidth + 'px';
                        }
                        if (thElems) 
                        {
                            thElems.style.width = columnWidth + 'px';
                        }
                        if (tfElems) 
                        {
                            tfElems.style.width = columnWidth + 'px';
                        }
                    });

                    //Done with the math ! We can just get rid of the clone
                    wrapper.remove();

                    // set css styles on thead and tbody
                    angular.element(elem.querySelectorAll('table[fixed-header]>thead, table[fixed-header]>tfoot')).css('display', 'block');
                    angular.element(elem.querySelector('table[fixed-header]>tbody')).css({
                        'display': 'block',
                        'height': 'inherit',
                        'overflow': 'auto'
                    });

                    // reduce width of last column by width of scrollbar
                    var tbody = elem.querySelector('table[fixed-header]>tbody');
                    if($attrs.tableHeight !== undefined && tbody.clientHeight > $attrs.tableHeight)
                    {
                        tbody.style.height = $attrs.tableHeight + 'px';
                    }
                    else
                    {
                        tbody.style.height = 'inherit';
                    }
                    var scrollBarWidth = tbody.offsetWidth - tbody.clientWidth;
                    var tBodyLastColumn = elem.querySelector('table[fixed-header]>tbody tr:first-child th:last-child, table[fixed-header]>tbody tr:first-child td:last-child');
                    var tHeadLastColumn = elem.querySelector('table[fixed-header]>thead tr:first-child th:last-child, table[fixed-header]>thead tr:first-child td:last-child');
                    var tFootLastColumn = elem.querySelector('table[fixed-header]>tfoot tr:first-child th:last-child, table[fixed-header]>tfoot tr:first-child td:last-child');
                    if (scrollBarWidth > 0) 
                    {
                        if(tHeadLastColumn && tBodyLastColumn)
                        {
                            tHeadLastColumn.style.width = (tBodyLastColumn.offsetWidth + scrollBarWidth) + 'px';
                        }
                        if(tFootLastColumn && tBodyLastColumn)
                        {
                            tFootLastColumn.style.width = (tBodyLastColumn.offsetWidth + scrollBarWidth) + 'px';
                        }
                        if(tHeadLastColumn && tBodyLastColumn)
                        {
                            tBodyLastColumn.style.width = tHeadLastColumn.offsetWidth - scrollBarWidth + 'px';
                        }
                    }
                    else
                    {
                        if(tHeadLastColumn && tBodyLastColumn)
                        {
                            tBodyLastColumn.style.width = tHeadLastColumn.offsetWidth + 'px';
                        }
                    }
                });
            }
        }
    }
})();

Hope this helps :)

Table lose full-width if resize window

I tested it on chrome and firefox.

The table head and body only get the width of it's initial value. For example, if i started with the browser windowed (without full width of screen) and then maximize to fill the screen, the table head/body will not expand to fill the table 100% width.

It stays on the initial size, only resize to full width after page reload

img on windowed mode

img on full width

Publish package on npm

Currently bower is just maintained.

It should be great to publish this project on npm.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.