Skip to content

Instantly share code, notes, and snippets.

@bantic
Last active October 25, 2020 04:39
Show Gist options
  • Save bantic/906c5c50bdeae3d9012eb9a1c3e4b66e to your computer and use it in GitHub Desktop.
Save bantic/906c5c50bdeae3d9012eb9a1c3e4b66e to your computer and use it in GitHub Desktop.
Ember Table Fixed Footer
import Ember from 'ember';
const alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
function makeRows(count, colCount, text='') {
return Array(count).fill().map((v,i) => {
return Array(colCount).fill().map((v,j) => alpha[j]).reduce((obj, letter) => {
obj[letter] = `${letter} ${text} ${i}`;
return obj;
}, {});
});
}
export default Ember.Controller.extend({
columns: Ember.computed('colCount', 'fixedCol', function() {
let names = Array(parseInt(this.colCount)).fill().map((v,i) => alpha[i]);
let cols = names.map(name => {
return {name, valuePath:name};
});
if (this.get('fixedCol')) {
cols[0].isFixed = 'left';
}
return cols;
}),
bodyRowCount: 30,
footRowCount: 10,
colCount: 5,
fixedCol: false,
bodyRows: Ember.computed('bodyRowCount', 'colCount', function() {
return makeRows(parseInt(this.get('bodyRowCount')),this.get('colCount'),'body');
}),
footRows: Ember.computed('footRowCount', 'colCount', function() {
return makeRows(parseInt(this.get('footRowCount')),this.get('colCount'),'foot');
}),
_setMaxFootRows(count) {
let tfoot = document.querySelector('tfoot');
let itemHeight = tfoot.querySelector('tr').getBoundingClientRect().height;
tfoot.querySelectorAll('tr').forEach((tr, trIndex) => {
let bottom = (count - trIndex) * itemHeight;
tr.querySelectorAll('td').forEach(td => {
if (bottom < 0) {
td.style.position = '';
td.style.bottom = '';
} else {
td.style.position = 'sticky';
td.style.bottom = `${bottom}px`;
}
});
});
},
actions: {
setRows(bodyCount, footCount) {
this.set('bodyRowCount', parseInt(bodyCount));
this.set('footRowCount', parseInt(footCount));
},
updateBodyCount(count) {
console.log(count);
if (Number.isNaN(parseInt(count))) { return; }
this.send('setRows', count, this.get('footRowCount'));
},
updateFootCount(count) {
if (Number.isNaN(parseInt(count))) { return; }
this.send('setRows', this.get('bodyRowCount'), count);
},
updateColCount(count) {
if (Number.isNaN(parseInt(count))) { return; }
this.set('colCount', parseInt(count));
},
toggleFixedCol() {
this.toggleProperty('fixedCol');
},
setMaxFootRows(count) {
if (Number.isNaN(parseInt(count))) { return; }
this._setMaxFootRows(parseInt(count));
}
}
});
body {
margin: 1em;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 12pt;
}
input {
width: 5em;
text-align: center;
font-family: sans-serif;
}
.table-container {
outline: 1px solid red;
height: 500px;
width: 400px;
}
thead th {
background-color: LightGreen;
}
tbody td {
background-color: lightpink;
}
tfoot td {
background-color: lightblue;
}
.fixed-col th:first-child, .fixed-col td:first-child {
border-right: 2px dotted black;
}
<h1>Demo Showing Fixed Footer</h1>
<br>
<p>
Footer cells are positioned so that they are always at the bottom of the table.
They are `position:sticky` with a calculated `bottom` value that ensures they are
in their "stuck" state rather than their scrollable state.
</p>
<p>
Note that the footer rows are stuck. Try increasing the number of rows. After ~20 they fill up the entire table and the body rows are not visible. The table content is still scrollable, but nothing changes while scrolling because the footer rows are all "stuck".
</p>
<br>
Body rows: <input type="number" value={{readonly bodyRowCount}} onchange={{action 'updateBodyCount' value="target.value"}} /><br>
Footer rows: <input type="number" value={{readonly footRowCount}} onchange={{action 'updateFootCount' value="target.value"}} /><br>
# Cols: <input type="number" value={{readonly colCount}} onchange={{action 'updateColCount' value="target.value"}} /><br>
Fixed left col: <input type="checkbox" checked={{fixedCol}} onchange={{action 'toggleFixedCol'}}/>
<br>
<br>
<button {{action 'setMaxFootRows' 5}}>Set max foot rows to 5</button> &lt;-- Click this to make footer rows scroll.
<br>
<br>
<div class='table-container {{if fixedCol 'fixed-col'}}'>
{{#ember-table as |t|}}
{{t.head columns=columns widthConstraint='gte-container'}}
{{t.body rows=bodyRows}}
{{t.foot rows=footRows}}
{{/ember-table}}
</div>
<br>
<br>
{
"version": "0.15.1",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js",
"ember": "3.4.3",
"ember-template-compiler": "3.4.3",
"ember-testing": "3.4.3"
},
"addons": {
"ember-data": "3.4.2",
"ember-table": "2.1.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment