Data Table sticky header



  • Have been playing around with this framework for a week now and love it! 🙂

    In the docs (0.13 and 0.14) for Data Tables there is mention of sticky headers, but cannot find any docs on how to use it! Anyone managed to get it working?

    Thanks!



  • You have to give the body a fixed height, then the header will become sticky and the body will scroll.

    From the docs in the config object section:

    {
      // (optional)
      // Styling the body of the data table;
      // "minHeight", "maxHeight" or "height" are important
      bodyStyle: {
        maxHeight: '500px'
      },
    }
    


  • @a47ae
    Working perfectly, thanks!



  • Hi, it seems this option does not work with version 0.15? Is there another option of make the data-table header stay fixed when scrolling. Same question for the footer.
    I would like to have the table expand to the full height of the parent element.



  • Good question. There is no description in 0.15 docs how to make header fixed.


  • Admin

    Unfortunately, having those sticky header/columns relies on too many things which the developer would need to do if they used scoped slots, so it’s not an option at the moment, sorry.


  • Admin

    You can, however, use: table-style prop, like this in your Vue templates: table-style="height: 400px".



  • I’ve done this, but there may be a better way.
    I have a property named height. The parent adjusts this accordingly using q-resize-observable to let the table know it’s height. My table is kept in a child component.

    My mounted function:

      mounted: function () {
        this.setTableHeight(this.height)
        this.setTableStickyTopRow(this.stickyHeader)
      },
    

    A computed function to return the table element (assuming you have a table with an id called ‘alerts’ - make adjustments as necessary):

        tableElement: function () {
          let element = null
          let tables = document.getElementsByTagName('TABLE')
          Array.prototype.forEach.call(tables, (table) => {
            if (table.parentElement.parentElement.id === 'alerts') {
              element = table.parentElement
            }
          })
          return element
        },
    

    In methods:

        setTableHeight: function (height) {
          if (this.tableElement) {
            this.tableElement.style.height = this.height + 'px'
          }
        },
    
        setTableStickyTopRow: function (bool) {
          if (this.tableElement) {
            if (bool) {
              this.tableElement.classList.add('sticky-table')
            }
            else {
              this.tableElement.classList.remove('sticky-table')
            }
          }
        },
    

    On occassion, there are items in the table programmatically selected. I hightlight the row and center it on the in the visible table. Here’s the snippet:

          // get the scroll window (parent of table)
          if (this.tableElement) {
            // get the visible height of the scollable window
            let clientHeight = this.tableElement.clientHeight
    
            // get alarm element
            let elem = document.getElementById(value)
            if (elem) {
              // calculate so that selected alarm is centered
              this.tableElement.scrollTop = elem.offsetTop - (clientHeight / 2)
            }
          }
    

    And finally the css:

    <style>
    .q-table thead, .q-table tr, .q-table th, .q-table td {
      height: 22px !important;
    }
    </style>
    
    <style lang="less">
    .sticky-table {
      thead tr:nth-child(1) th{
        // background: #efffff;
        background: lightgrey;
        position: sticky;
        top: 0;
        z-index: 10;
      }
    }
    
    table {
      thead tr:nth-child(1) th{
        background: lightgrey;
      }
    }
    </style>
    

    Hope it helps!

    Edit: if interested, here is from the parent page (this is not on the table, but elements above the table that know how to resize themselves based on content):
    html:

    <q-resize-observable  @resize="onCameraWindowContainerResize" />
    

    methods:

        onCameraWindowContainerResize: function (size) {
          this.cameraWindowContainerWidth = size.width
          this.cameraWindowContainerHeight = size.height
          // console.log('cameraWindowContainerHeight', this.cameraWindowContainerHeight)
          this.adjustAlarmsTableHeight()
        },
    
        adjustAlarmsTableHeight: function () {
          if (this.displayedCameras.length === 0) {
            let height = 73 // toolbar
            height += 40 // live view caption
            this.alarmsTableHeight = this.windowSize.height - height
          }
          else if (this.cameraWindowContainerHeight) {
            let height = 73 // toolbar
            height += 40 // live view caption
            height += this.cameraWindowContainerHeight
            this.alarmsTableHeight = this.windowSize.height - height
          }
        },
    

    The alarmsTableHeight is passed in as :height="alarmsTableHeight" to my table component.



  • here is the missing html from above. It got tagged as SPAM from askinet:

    <q-resize-observable  @resize="onCameraWindowContainerResize" />
    

    and the this.windowSize.height comes from:

    <q-window-resize-observable @resize="onWindowResize" />
    

    at the top of the page template.