Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
Dashrath_Singh
Explorer
 

Objective


Extend a base control with a fully working SmartVariantManagement. This can be used as single Smart Variant Manager for multiple controls(Tables, Filters, Charts etc.).

It requires minimal effort with the filters data, the rest is already implemented!

Backstory


We had a requirement where we need to implement Variant Management for a simple UI table. Later the requirement got changed to club multiple controls in same variant management (Similar to List Report Floorplan where Filter and Table's changes can be stored in Single Variant).

As we were not using Smart Tables/Filters but created simple UI tables. So initially I used simple Variant Management but it need lot of coding to mange the variants. Thanks for this amazing blog which explains everything in detail.

https://blogs.sap.com/2017/01/12/variant-management-implementation-using-shell-personalization-servi...

Now instead of Variant Management, we would like to use Smart Variant Management . This will reduce lot of coding from UI. Thanks to alex.necula  for this amazing blog where he explained all the details for using Smart Variant Management for (Non Smart :P) UI Table OR Filterbar. I would recommend to go through Alex's blog before going through this one.

But our motive was not to extend all the controls (UI table, FilterBar, M table etc) instead of that, extend a base control and trigger Smart Variant Management using that Extended Base control.

To understand basics of Smart Variant Management with FilterBar, we can refer SAP Documentation.

Implementation


The SAPUI5 version I have worked on is the latest one (1.118.0) but it should work with older version like 1.60.

Extend the Base Core control


/* eslint-disable linebreak-style */
sap.ui.define([
"sap/ui/core/Control",
"sap/base/Log"
], function(
Control,
Log
) {
"use strict";

let customVariant = Control.extend("com.sap.sample.variant.samplevariant.custom.customVariant", {
renderer: function (oRm, oControl) {
Control.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.
*/
customVariant.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.
*/
customVariant.prototype.registerApplyData = function (fCallBack) {

this._fRegisteredApplyData = fCallBack;

return this;
};

/**
* Creates and returns the variant representation.
* @returns {object} JSON object
* @public
*/
customVariant.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
*/
customVariant.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 customVariant;
});

Load this control in Controller file


onBeforeRendering : function(){
this._customVariant = new customVariant(this.createId("customVariant"),{persistencyKey:"commanKey"});
},

Add this control to Smart Variant Management


onAfterRendering : function(){

var oPersInfo = new PersonalizableInfo({
keyName: "persistencyKey",
type: "table"
});
oPersInfo.setControl(this._customVariant);
this._oSmartVariantManagement.addPersonalizableControl(oPersInfo);

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

this._customVariant.registerFetchData(this.onVariantFetchData.bind(this));
this._customVariant.registerApplyData(this.onVariantApplyData.bind(this));
},

onVariantFetchData: function () {

const aColumnsData = [];
this.getView().byId("idUiTable")._getVisibleColumns().forEach((oColumn, index) => {
const aColumn = {};
aColumn.fieldName = oColumn.getProperty('name');
aColumn.Id = oColumn.getId();
aColumn.index = index;
aColumn.width = oColumn.getWidth();
aColumn.Visible = oColumn.getVisible();
aColumn.filterProperty = oColumn.getProperty('filterProperty');
aColumn.sortProperty = oColumn.getProperty('sortProperty');
aColumn.sorted = oColumn.getProperty('sorted');
aColumn.sortOrder = oColumn.getProperty('sortOrder');
aColumn.defaultFilterOperator = oColumn.getProperty('defaultFilterOperator');
aColumnsData.push(aColumn);
});

return {
"ColumnsVal": aColumnsData,
"ButtonProp": {
text:this.byId("testBtn").getText(),type:this.byId("testBtn").getType()
}
};
},

onVariantApplyData: function (oData) {
let buttonProp = oData.ButtonProp;
if(buttonProp){
this.byId("testBtn").setText(buttonProp.text);
this.byId("testBtn").setType(buttonProp.type);
}

const aColumns = oData.ColumnsVal;
// Hide all columns first
this.getView().byId('idUiTable').getColumns().forEach((oColumn) => {
oColumn.setVisible(false);
});
// re-arrange columns according to the saved variant
aColumns.forEach((aColumn) => {
const aTableColumn = $.grep(this.getView().byId('idUiTable').getColumns(), (colObj, id) => colObj.getProperty('name') === aColumn.fieldName);
if (aTableColumn.length > 0) {
aTableColumn[0].setVisible(aColumn.Visible);
aTableColumn[0].setWidth(aColumn.width);
aTableColumn[0].setFilterProperty(aColumn.filterProperty);
aTableColumn[0].setSortProperty(aColumn.sortProperty);
aTableColumn[0].setDefaultFilterOperator(aColumn.defaultFilterOperator);
aTableColumn[0].setSorted(aColumn.sorted);
aTableColumn[0].setSortOrder(aColumn.sortOrder);
this.getView().byId('idUiTable').removeColumn(aTableColumn[0]);
this.getView().byId('idUiTable').insertColumn(aTableColumn[0], aColumn.index);
}
});

},

Smart Variant Management captures the changes of Button and UI Table


<mvc:View controllerName="com.sap.sample.variant.samplevariant.controller.View1"
xmlns:mvc="sap.ui.core.mvc" displayBlock="true"
xmlns="sap.m"
xmlns:l="sap.ui.layout"
xmlns:table="sap.ui.table"
xmlns:smartVariantManagement="sap.ui.comp.smartvariants"
>
<Page id="page" title="{i18n>title}">
<content >
<l:VerticalLayout>
<smartVariantManagement:SmartVariantManagement
id="pageVariantId"
persistencyKey="PageVariantPKey"/>
<table:Table id="idUiTable" columnMove="handleColumnMove" rows="{/Suppliers}">
<table:extension>
<OverflowToolbar>
<Button id="testBtn" text="Accept" type="Accept" press="onButtonPress"/>
<ToolbarSpacer/>
<Button icon="sap-icon://action-settings" type="Emphasized"
class="sapUiTinyMarginEnd" width="2em"
press="onPersonalizeColumns" />
</OverflowToolbar>
</table:extension>
<table:columns>
<table:Column id="idUiIDColumn" name="{i18n>View1View.Id}">
<Label text="{i18n>View1View.Id}"/>
<table:template>
<Text text="{Id}" />
</table:template>
</table:Column>
<table:Column id="idUiNameColumn" name="{i18n>View1View.Name}">
<Label text="{i18n>View1View.Name}"/>
<table:template>
<Text text="{Name}" />
</table:template>
</table:Column>
<table:Column id="idUiEmailColumn" name="{i18n>View1View.Email}">
<Label text="{i18n>View1View.Email}"/>
<table:template>
<Text text="{Email}" />
</table:template>
</table:Column>
</table:columns>
</table:Table>

</l:VerticalLayout>
</content >
</Page>

</mvc:View>

The whole source code can be found on my GitHub.

Example:


Initial Standard view contains, 3 columns in UI table and 1 sap.m.Button with text and type as "Accept".


Let's deselect Email column and Press Accept button so text and type is changed to "Emphasized". After that, let's save the Variant as Demo.




When we save it, we can see 2 service calls. One stores the variant data(selected one) and another one will define details of the default variant. We have defined persistencyKey as "CommanKey". This captures both the changes of Table as well as Button.


 

I have used ES5 system for this demo. I would like to show where all these variants are stored but  ES5 stopped webgui version 😞 So for that reason, I am calling the service in browser and showing the details:


When we have regular netweaver gateway system, we can check all the information in tcode -  SUI_SUPPORT. We can search it by providing our user id and application namespace. User ID, application namespace is available in upper screenshot.



 

Conclusion


I hope this will help you to reduce lot of coding from normal variant management and use the features of Smart Variant Management.
2 Comments
Labels in this area