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/).

2. Post Render Tutorial

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

Frozen Columns Example

2.1. Prerequisites

  • An running Helium environment

  • Basic javascript, HTML and CSS understanding

2.2. Configure a Widget with a Post Render function

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.

2.3. Create the Post Render function

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.

2.4. Styling our frozen columns

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.

2.5. Browser support for this example

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