24 January 2020
© Copyright 2015-2019 by TECHNIA AB
All rights reserved.
PROPRIETARY RIGHTS NOTICE: This documentation is proprietary property of TECHNIA AB. In accordance with the terms and conditions of the Software License Agreement between the Customer and TECHNIA AB, the Customer is allowed to print as many copies as necessary of documentation copyrighted by TECHNIA relating to the software being used. This documentation shall be treated as confidential information and should be used only by employees or contractors with the Customer in accordance with the Agreement.
This product includes software developed by the Apache Software Foundation. (http://www.apache.org/).
In this tutorial we will add a PostRender
function to a table widget to freeze configured columns.
Things that will be covered:
Configure a Widget with a PostRender function
Create a Post Render function
Add some styling
Browser support for this example
The first thing to do is add a <PostRender>
function to a Widget Configuration
.
In our case we want it to be a DataTable Widget since we are working with columns.
<?xml version="1.0" encoding="UTF-8"?>
<DataTable>
<Title>EBOM</Title>
<TableConfig namespace="helium:demo:parts">EBOM.xml</TableConfig>
<Responsive>false</Responsive>
<FixedHeader>true</FixedHeader>
<PostRender>App.custom.freezeColumns</PostRender>
<OnInitOption name="freeze" value="primary-image,State" />
</DataTable>
We also add a <OnInitOption>
called freeze
where we specify the column names we want to freeze.
In this way, you can pass any settings to your postRender functions as needed.
This setting will later be used by our function to freeze the columns.
Add a javascript function. In this case we should add it as App.custom.freezeColumns
as we specified in the Widget configuration.
freezeColumns: function() {
var _this = this;
// Finds frozen elements and adjusts left offset
var onResize = function() {
this.element.find('.frozen-column').each(function(i, el) {
var $el = $(el);
var offset = 0;
$el.prevAll('.frozen-column').each(function(i, element) {
offset += $(element).outerWidth();
});
$el.css({ left: `${offset}px` });
});
};
if (this.options.freeze && isStickySupported()) {
// Get names of configured columns to be frozen
var freezeNames = $.map(this.options.freeze.split(','), function(s) {
return s.trim();
});
// Set frozen-column class on configured columns
$.each(this.columns, function(i, col) {
if (freezeNames.includes(col.name)) {
var elements = _this.dataTable.column(i).nodes().toArray();
elements.push(_this.config.getFilterHeaders()[i]);
elements.push(_this.config.getHeaders()[i]);
elements.forEach(function (el) {
$(el).addClass('frozen-column');
});
}
});
// Add listener to dataTable event to handle resizing
this.dataTable.on('column-sizing', onResize.bind(this));
// Initially adjust offset after load
setTimeout(() => {
onResize.bind(this)();
}, 100);
}
}
This function will find the columns we specified in our freeze
option and do two things.
Calculate the left
property based on other frozen columns and add the css class frozen-column
to each cell.
To "freeze" our columns we need to set them as position: sticky;
and set a background-color
on each cell.
This can be done with the frozen-column
class we added with our post render function.
table.dataTable.helium-table > thead > tr > th.frozen-column {
position: -webkit-sticky;
position: sticky;
}
table.dataTable.helium-table > tbody > tr > td.frozen-column {
position: -webkit-sticky;
position: sticky;
}
table.dataTable.helium-table > tbody > tr.even > td.frozen-column {
background-color: #fafafb;
}
table.dataTable.helium-table > tbody > tr.odd > td.frozen-column {
background-color: white;
}
This together with the left
property we set programmatically in the previous step will make the columns stick to the left side of the table when scrolling horizontally.
Depending on your implementation you may have to add further styling.
The position: sticky
property is not supported in all browsers. It has known issues with IE and can have issues with older browsers.
If you dont want to unnecessarily modify the DOM you can add a function to verify that the browser supports position: sticky
before modifying the DOM.
var isStickySupported = function() {
var prefix = ['', '-o-', '-webkit-', '-moz-', '-ms-'];
var test = document.head.style;
for (var i = 0; i < prefix.length; i += 1) {
test.position = `${prefix[i]}sticky`;
}
return test.position !== '';
}
if (this.options.freeze && isStickySupported()) {
...
}
To check current browser support and known issues you can check caniuse. You can find the code used in this tutorial under:
helium/custom/example.js
helium/custom/example.css