Skip to Content

In SAPUI5 application we often use sap.m.table instance directly or via the sap.ui.comp.smarttable.SmartTable.

One of the problems is how to keep the header toolbar and table’s header on top when we do scrolling.

In the following picture  you can see what happen when we scrolling in the worklist table which has a smart table and a sap.m.table as its including instance table.

But what we expect is to have the both custom toolbar and table’s header on top while scrolling.

 

Since version 1.54 of the SAPUI5 you can use the sticky attribute of the sap.m.table and then keep the header of the table on top. At the moment this attribute only accept 2 values.

  1. sap.m.Sticky.ColumnHeaders which only keeps the column headers in a fixed position
  2. sap.m.Sticky.None

Thus if we define a sap.m.table instance like the following:

<m:Table id="table" mode="MultiSelect" sticky="ColumnHeaders"> 
.... 
</m:Table>

Then we will have something like this when scrolling:

Fine, it is better than previous that we had no header on top. But still if user wants to use the buttons inside of the toolbar need to scroll down, then select the row(s) and then scroll up to use the buttons inside of the toolbar.

Let’s take a deeper look on what has been added to our html dom elements when we use this attribute:

Actually one css class which is called sapMListTblStickyColHdr has been added to the header of the table. And in the css part we have these:

.sapMListTblStickyColHdr, html[data-sap-ui-browser^='cr'] 
.sapMListTblStickyColHdr>.sapMTableTH {
    position: sticky;
    position: -webkit-sticky;
    top: 0;
    z-index: 100;
}

So we can use the same idea to keep the custom toolbar of our smartTable on top. Then let’s add some custom css and add a custom css class to our custom toolbar:

<smartTable:customToolbar>
	<m:OverflowToolbar id="stickyToolbar" design="Solid" class="stickyToolbar">
		<m:ToolbarSpacer/>
			<m:SearchField id="searchField" tooltip="Search" width="auto" search="onSearch" liveChange="onSearchLiveChange"/>
			<m:Button type="Transparent" press="onCreateBtnPress" icon="sap-icon://add" tooltip="Add"/>
			<m:Button type="Transparent" press="onDeleteBtnPress" icon="sap-icon://delete" tooltip="Delete"/>
	</m:OverflowToolbar>
</smartTable:customToolbar>

And the custom css which is normally placed inside of the style.css file must have:

.stickyToolbar {
    position: sticky;
    position: -webkit-sticky;
    top: 0;
    z-index: 101;
}

Please note that we assigned the z-index to 101 (one value more than what we saw in sapMListTblStickyColHdr class).

But still it does not work, and the reason is that the class has been assigned to a deeper dom element. While if we assign it to its parent all would work.

So we will use the onAfterRendering event of the smart table to assign the css class to toolbar’s parent. If you noticed, we assigned one id to our custom toolbar then we will use that id to retrieve it.

// This function must be bound to the view's afterRendering event
onAfterRendering: function() {
	// Stick the toolbar and header of the smart table to top. 
	var oSmartTable = this.byId("__smartTableWorklist");
	oSmartTable.onAfterRendering = function() {
		var oToolbar = this.byId("stickyToolbar"),
			oParent = oToolbar.$().parent();
		if (oParent) {
			oParent.addClass("stickyToolbar");
		}
	}.bind(this);	
},

As you can see in the above code we found the parent dom element of our custom toolbar. (In the previous figure it is a div with “__data28” as its id). Here is the result:

OK, not bad. But now we have another problem. We could keep the custom toolbar on top but as it is seen the header is going to be hide under the custom toolbar as soon as we scroll (The yellow highlight in the above picture). The reason is because of top property of the table’s header. Actually it will also stay on top but under the custom toolbar as it has smaller z-index. If you want to see it, just change the z-index of the stickyToolbar to some value smaller than 100. You can see the result of this change here:

Yeah, you can see now the table’s header move to places on top to 0 point in Y-axel.
Let’s return the z-index to 101 again. We have to actually set the top property of the table’s header to a value equal to the outer height of the custom toolbar in runtime.

For this, we simply remove the sticky property of the sap.m.table instance and then will generate a custom css in runtime and assign it in the afterRendering event of the table. Here are the steps:

  1. Remove the sticky property from table instance:
    <m:Table id="table" mode="MultiSelect">​
  2. Change the afterRendering method of the view like this:
    onAfterRendering: function() {
    	// Stick the toolbar and header of the smart table to top. 
    	var oSmartTable = this.byId("__smartTableWorklist");
    	oSmartTable.onAfterRendering = function() {
    		var oToolbar = this.byId("stickyToolbar"),
    		    oParent = oToolbar.$().parent();
    		if (oParent) {
    			oParent.addClass("cimtStickyToolbar");
    		}
    	}.bind(this);
            // This is new code to make the table's header also sticky
    	var oTable = this.byId("table");
    	oTable.onAfterRendering = function() {
    		oTable.addStyleClass("cimtStickyTableMSW");
    		var oToolbar = this.byId("stickyToolbar"),
    		iTop = oToolbar.$().outerHeight();
    		if ($("head").find("style#cimtStickyTableMSW").length !== 0) {
    			$("head").find("style#cimtStickyTableMSW").remove();
    		}
    		var style = $("<style id='cimtStickyTableMSW'></style>");
    		$(style).html(" .cimtStickyTableMSW > table > thead > tr," +
    			".cimtStickyTableMSW > table > thead > tr > th {" +
    			"	position: sticky;" +
    			"	position: -webkit-sticky;" +
    			"	top: " + iTop + "px;" +
    			"	z-index: 100;" +
    			"}");
    		$("head").prepend(style); //eslint-disable-line
    	}.bind(this);
    }, // end of afterRendering handler of the view. ​

As you have seen, here we added a new style element on runtime to the head tag of the page. I know it is not recommended but it is the best place to add the style tag, to be able to remove it for the next times that we need to change the top attribute based on another rendering situation (the height of the custom toolbar can be vary).

And here is the final result:

I hope you find this post useful.

To report this post you need to login first.

2 Comments

You must be Logged on to comment or reply to a post.

Leave a Reply