Skip to Content
Technical Articles

SAPUI5 Table with SmartVariantManagement

Objective

Add Smart Variant Management mechanism to an SAPUI5 non-smart table (sap.ui.table, sap.m.table etc.).

For a guide regarding FilterBar (sap.ui.comp.filterbar.FilterBar) please read my other blog post:

https://blogs.sap.com/2020/07/20/sapui5-filterbar-with-smartvariantmanagement

Backstory

The business requirement was to use the same features of a SmartTable variant management with a basic table.

The solution approached in this blog uses sap.ui.comp.smartvariants.SmartVariantManagement which needs minimal implementation effort.

Implementation

The SAPUI5 version I have worked on is 1.60. The control extended for this tutorial is TreeTable but you can use whatever fits your case.

The TreeTable.js file

Use this the same way you would use the standard TreeTable by including the xml namespace for custom.control.

sap.ui.define([
	"sap/ui/table/TreeTable",
	"sap/base/Log"
], function (TreeTable, Log) {
	"use strict";

	var CustomTreeTable = TreeTable.extend("custom.control.controller.TreeTable", {
		renderer: function (oRm, oControl) {
			TreeTable.getMetadata().getRenderer().render(oRm, oControl);
		},

		metadata: {
			properties: {
				/**
				 * Key used to access personalization data.
				 */
				persistencyKey: {
					type: "string",
					group: "Misc",
					defaultValue: ""
				}
			}
		}
	});

	/**
	 * Registration of a callback function. The provided callback function is executed
	 * when saving a variant is triggered and must provide all relevant fields and values in JSON.
	 * @public
	 * @param {function} fCallBack Called when a variant must be fetched
	 * @returns {sap.ui.table.TreeTable} Reference to this in order to allow method chaining.
	 */
	CustomTreeTable.prototype.registerFetchData = function (fCallBack) {

		this._fRegisteredFetchData = fCallBack;

		return this;
	};

	/**
	 * Registration of a callback function. The provided callback function is executed
	 * when a variant must be applied.
	 * The callback function will receive the corresponding data set containing all relevant data in JSON,
	 * as initially provided by the callback for fetchData.
	 * @public
	 * @param {function} fCallBack Called when a variant must be applied
	 * @returns {sap.ui.table.TreeTable} Reference to this in order to allow method chaining.
	 */
	CustomTreeTable.prototype.registerApplyData = function (fCallBack) {

		this._fRegisteredApplyData = fCallBack;

		return this;
	};

	/**
	 * Creates and returns the variant representation.
	 * @returns {object} JSON object
	 * @public
	 */
	CustomTreeTable.prototype.fetchVariant = function () {
		if (this._fRegisteredFetchData) {
			try {
				return this._fRegisteredFetchData();
			} catch (ex) {
			    Log.error("callback for fetching data throws an exception");
			}
		} else {
			Log.warning("no callback for fetch data supplied");
		}

		return {};
	};

	/**
	 * Triggers the registered callBack for applying the variant data.
	 * @private
	 * @param {object} oVariant the data blob representing part of the variant content
	 * @returns {object} data to be stored as part of the variant content
	 */
	CustomTreeTable.prototype.applyVariant = function (oVariant) {

		if (this._fRegisteredApplyData) {
			try {
				return this._fRegisteredApplyData(oVariant);
			} catch (ex) {
				Log.error("callback for applying data throws an exception");
			}
		} else {
			Log.warning("no callback for appy data supplied");
		}

		return null;
	};

	return CustomTreeTable;
});

In the onAfterRendering event, create a personalizable info of type table and append it to the table object. This links the variant management to the control.

var oPersInfo = new PersonalizableInfo({
	keyName: "id",
	type: "table"
});

oPersInfo.setControl(this._oTable);
this._oSmartVariantManagement.addPersonalizableControl(oPersInfo);

Events

Still in the onAfterRendering event of the controller, initialise the variant management and attach the handlers for fetchData and appendData. You will have to create these handlers. On the initialising event, the variant management is set as not modified.

this._oSmartVariantManagement.initialise(function () {
	this._oSmartVariantManagement.currentVariantSetModified(false);
}.bind(this), this._oTable);

this._oTable.registerFetchData(this.onTableFetchData.bind(this));
this._oTable.registerApplyData(this.onTableApplyData.bind(this));

Write the registered methods

The onTableFetchData method should return a custom JSON with relevant data for the table (for example column configuration, sorters, filters or grouping).

onTableFetchData: function () { … }

The onTableApplyData method gets the above saved JSON as a parameter for the selected variant. Use this to modify the table.

onTableApplyData: function (oVariantContent) { … }

These two methods are the only things you have to implement based on your use case.

The options Set As Default, Public (sharing with transports included), Apply Automatically, Add as Favorite, Delete, Rename should work out of the box.

Dirty State

If you implement the P13n features (like grouping), you will most likely want to be able to save the variant after the OK button of the dialog is pressed. You can do this by adding this line to the ok event.

this._oSmartVariantManagement.currentVariantSetModified(true);

Conclusion

This control should be implemented by default for any table in your future freestyle SAP Fiori apps as it has very little drawbacks (time of implementation) and many advantages.

Be the first to leave a comment
You must be Logged on to comment or reply to a post.