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: 
rahulkumar_sankla
Participant
Often, we come to a situation where users request to add personalization on UI table so that they can store the view according to their needs and can easily view the required information at just a click of a button.

We are very familiar with the use of sap.ui.table to show data in tabular form as it is very easy to manipulate this form of UI control, plus it offers a lot of flexibility to cater our needs as well. The only thing that it lacks is the personalization. Of course, the table personalization can be added using sap.ui.table.TablePersoController which can control the visibility of the columns, but they won’t be persistent.

So, in order to make it persistent, we can add VariantManagement control to our FIORI application table along with the TablePersoController and store this information in persistent DB offered by backend ABAP system.

The variant management could look like as below screenshot:



The first thing we need to do here is to add this Variant Management control (sap.ui.comp.variants.VariantManagement) to our UI. The below code snippet can be added in the extension or toolbar (deprecated in the new versions) area of the UI table.
<Table id="DemoTableUI" visibleRowCountMode="Fixed" selectionBehavior="Row" selectionMode="None">
<extension>
<m:Toolbar>
<m:content>
<!--add variant management-->
<variant:VariantManagement variantItems="{/VariantList}" select="onSelect" save="onSaveAs" enabled="true" manage="onManage" showExecuteOnSelection="false" showShare="false" id="Variants">
<variant:variantItems>
<variant:VariantItem text="{Name}" key="{Key}"/>
</variant:variantItems>
</variant:VariantManagement>
<m:ToolbarSpacer/>
<m:Button icon="sap-icon://action-settings" press="onPersoButtonPressed" tooltip="Columns Settings"/>
</m:content>
</m:Toolbar>
</extension>

The above code will add the variant management control on the toolbar of the UI Table. The button is added to add the table persco controller which will open up the list of the columns to be set as visible or invisible according to the need.

To setup the variant management and to connect the variant management with the backend system, the ushell services (Unified Shell services) will be used.

the code snapshot is shown below that will invoke the service:
// Peronalisation from ushell service to persist the settings
if (sap.ushell && sap.ushell.Container && sap.ushell.Container.getService) {

var oComponent = sap.ui.core.Component.getOwnerComponentFor(this.getView());
this.oPersonalizationService = sap.ushell.Container.getService("Personalization");
var oPersId = {
container: "TablePersonalisation", //any
item: "DemoTableUI" //any- I have used the table name
};
// define scope
var oScope = {
keyCategory: this.oPersonalizationService.constants.keyCategory.FIXED_KEY,
writeFrequency: this.oPersonalizationService.constants.writeFrequency.LOW,
clientStorageAllowed: true
};
// Get a Personalizer
var oPersonalizer = this.oPersonalizationService.getPersonalizer(oPersId, oScope, oComponent);
this.oPersonalizationService.getContainer("TablePersonalisation", oScope, oComponent)
.fail(function() {})
.done(function(oContainer) {
this.oContainer = oContainer;
this.oVariantSetAdapter = new sap.ushell.services.Personalization.VariantSetAdapter(this.oContainer);
// get variant set which is stored in backend
this.oVariantSet = this.oVariantSetAdapter.getVariantSet("DemoTableUISet");
if (!this.oVariantSet) { //if not in backend, then create one
this.oVariantSet = this.oVariantSetAdapter.addVariantSet("DemoTableUISet");
}
// array to store the existing variants
Variants = [];
// now get the existing variants from the backend to show as list
for (var key in this.oVariantSet.getVariantNamesAndKeys()) {
if (this.oVariantSet.getVariantNamesAndKeys().hasOwnProperty(key)) {
var oVariantItemObject = {};
oVariantItemObject.Key = this.oVariantSet.getVariantNamesAndKeys()[key];
oVariantItemObject.Name = key;
Variants.push(oVariantItemObject);
}
}
// create JSON model and attach to the variant management UI control
this.oVariantModel = new sap.ui.model.json.JSONModel();
this.oVariantModel.oData.Variants = Variants;
this.getView().byId("Variants").setModel(this.oVariantModel);
}.bind(this));
// create table persco controller
this.oTablepersoService = new TablePersoController({
table: this.getView().byId("DemoTableUI"),
persoService: oPersonalizer
});

}

 

sap.ushell.Container.getService("Personalization") will get the instance of the Personalization service from the unified shell which will be used to store the information to the backend system.

This method uses the container mode to persist the variants. Ultimately, we will add values that need to be stored and save them in the container to persist them.

Since, this gives us an oData service to read and write data, we need to get the instance of the adapter to do so. Thus we create an instance of the variant set adapter.

The other thing to notice is that the we need to create our own variant set name. Here I have used the table ID as the variant set name for simplicity but this is up to you.

this.oVariantSetAdapter.addVariantSet will add the new variant set for the application to the service and persist it in the backend. once, we have this in place, we can CRUD the variants in this variant set.

The Table Perso Controller used here is with the accordance to the table i.e. from the control sap.ui.table.TablePersoController.

The code above will not only invoke the variant management service but also attach the perso controller to the table. The perso controller also uses the unified shell service and renders according to the table instance specified in it.

To use the perso controller, we will add code to open the column list on the press event of the button on the toolbar labelled as settings
onPersoButtonPressed: function(oEvent) {
this.oTablepersoService .openDialog({
ok: "this.onPerscoDonePressed.bind(this)"
});
this.oTablepersoService ._oDialog.attachConfirm(this, this.onPerscoDonePressed.bind(this));
},
onPerscoDonePressed: function(oEvent) {
this.oTablepersoService .savePersonalizations();
},

 

Thus, on pressing the button, the screen containing the column list will popup from which the user can select or un-select to un-hide or hide the column respectively. All the columns details are coming from the table instance provided to the perso controller.



Now comes the interesting part, saving and managing the variant. Once the user chooses the columns that are to visible including their position, he/she can press the variant management button to save the personalization.



on pressing OK button on the popup, the event handler method ""onSaveAs" will be fired. The below code snapshot will store the variant with the columns settings including the order to the backend
		onSaveAs: function(oEvent) {
// get variant parameters:
var VariantParam = oEvent.getParameters();
// get columns data:
var aColumnsData = [];
this.getView().byId("DemoTableUI").getColumns().forEach(function(oColumn, index) {
var aColumn = {};
aColumn.fieldName = oColumn.getProperty("name");
aColumn.Id = oColumn.getId();
aColumn.index = index;
aColumn.Visible = oColumn.getVisible();
aColumnsData.push(aColumn);
});

this.oVariant = this.oVariantSet.addVariant(VariantParam.name);
if (this.oVariant) {
this.oVariant.setItemValue("ColumnsVal", JSON.stringify(aColumnsData));
if (VariantParam.def === true) {
this.oVariantSet.setCurrentVariantKey(this.oVariant.getVariantKey());
}
this.oContainer.save().done(function() {
// Tell the user that the personalization data was saved
});
}
},

The arguments of this method will provide the Variant information entered by the user. to read, we need to use the method oEvent.getParameters(to get those values.

The above code will store the table's column information required to be stored in an local array. The important information required are column name, its ID, the index of the column and its visibility. Of course, the other information like sorting etc can also be stored but it is entirely based on the requirement.

The variant created do not store array but store the content as a string, so it is absolutely important to convert the array/object to a string value using JSON.stringify() method.

Once, all the information is written to the variant set, the container can be saved.

One more thing here to notice is that to store values the method setItemValue() is used. to store multiple information to the same variant, this method can be called multiple times with different arguments. for e.g.

this.oVariant.setItemValue("ColumnsVal1", JSON.stringify(aColumnsData));

this.oVariant.setItemValue("ColumnsVal2", JSON.stringify(aColumnsData));

This is helpful in case to something like a filter value to be stored.

the below snapshot shows the stored variant



When user chooses the variant from the above list, we need to read the service and change the table columns accordingly.. Below is the code to do so:
		onSelect: function(oEvent) {
var selectedKey = oEvent.getParameters().key;
for (var i = 0; i < oEvent.getSource().getVariantItems().length; i++) {
if (oEvent.getSource().getVariantItems()[i].getProperty("key") === selectedKey) {
var selectedVariant = oEvent.getSource().getVariantItems()[i].getProperty("text");
break;
}
}
this._setSelectedVariantToTable(selectedVariant);
},

_setSelectedVariantToTable: function(oSelectedVariant) {
if (oSelectedVariant) {
var sVariant = this.oVariantSet.getVariant(this.oVariantSet.getVariantKeyByName(oSelectedVariant));
var aColumns = JSON.parse(sVariant.getItemValue("ColumnsVal"));

// Hide all columns first
this.getView().byId("DemoTableUI").getColumns().forEach(function(oColumn) {
oColumn.setVisible(false);
});
// re-arrange columns according to the saved variant

aColumns.forEach(function(aColumn) {
var aTableColumn = $.grep(this.getView().byId("DemoTableUI").getColumns(), function(el, id) {
return el.getProperty("name") === aColumn.fieldName;
});
if (aTableColumn.length > 0) {
aTableColumn[0].setVisible(aColumn.Visible);
this.getView().byId("DemoTableUI").removeColumn(aTableColumn[0]);
this.getView().byId("DemoTableUI").insertColumn(aTableColumn[0], aColumn.index);
}
}.bind(this));
}
// null means the standard variant is selected or the variant which is not available, then show all columns
else {
this.getView().byId("DemoTableUI").getColumns().forEach(function(oColumn) {
oColumn.setVisible(true);
});
}
},

To read the variant's data, this.oVariantSet.getVariant() is called and to convert the stored values back into the array JSON.parse() is used. Once we have this information, we can modify the table and refresh the table control to show that data on the screen.

The variants can be managed as well. on pressing the manage button the user will get a screen like below:



he/she can change the name or delete the variant or can make anyone of them as default. to manage this, the below code snippet will do so:
onManage: function(oEvent) {
var aParameters = oEvent.getParameters();
// rename variants
if (aParameters.renamed.length > 0) {
aParameters.renamed.forEach(function(aRenamed) {
var sVariant = this.oVariantSet.getVariant(aRenamed.key),
sItemValue = sVariant.getItemValue("ColumnsVal");
// delete the variant
this.oVariantSet.delVariant(aRenamed.key);
// after delete, add a new variant
var oNewVariant = this.oVariantSet.addVariant(aRenamed.name);
oNewVariant.setItemValue("ColumnsVal", sItemValue);
}.bind(this));
}
// default variant change
if (aParameters.def !== "*standard*") {
this.oVariantSet.setCurrentVariantKey(aParameters.def);
} else {
this.oVariantSet.setCurrentVariantKey(null);
}
// Delete variants
if (aParameters.deleted.length > 0) {
aParameters.deleted.forEach(function(aDelete) {
this.oVariantSet.delVariant(aDelete);
}.bind(this));
}
// Save the Variant Container
this.oContainer.save().done(function() {
// Tell the user that the personalization data was saved
});
},

Th event parameter will provide the values of all the data changed on the variant manage screen. The methods called are pretty straightforward to change, delete and make default variant.

The above code is the final piece of the puzzle to be in place for this variant management control to work with the table.

One last important information, the backend service used by ushell personalisation service  is INTEROP with name space /UI2/



I hope the above information helps you and if there are any challenges, please comment .

References:

https://sapui5.hana.ondemand.com/#/api/sap.ui.comp.variants

https://sapui5.hana.ondemand.com/#/api/sap.ushell.services.Personalization

https://help.sap.com/viewer/a7b390faab1140c087b8926571e942b7/1709.001/en-US/755536526c384096b5f37d15...

Many thanks

Rahul
40 Comments
Labels in this area