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: 
Former Member
Variant management:

The standard fiori variant management control allows the user to save the variant, open the existing variant(read variant) ,update the existing variant and delete the variant. It also allows to set the default variant.

This post targets at the implementation of variant management using the shell personalization service.

We used variant management control in combination with filter bar.



To start with personalization service of shell, we need to create the personalization container and variant set specific to our application. We can also create a different variant set for the default variant. Personalization variant set contains variants of personalization data.

View:

View with Filter bar and variant management control is as below. Filter items to the filter bar are added dynamically in the controller


<variant:VariantManagement variantItems="{/Variants}" standardItemText="{/DefaultVariant}" select="onSelectVariant" 
save="onSaveAsVariant" enabled="true" manage="onManageVariant" showExecuteOnSelection="false" showShare="false" id="variantManagement">
<variant:variantItems>
<variant:VariantItem text="{VariantName}" key="{VariantKey}" selectionKey= "{VariantKey}"/>
</variant:variantItems>
</variant:VariantManagement>
<fb:FilterBar reset="onReset" search="OnPressOfApplyInFilterBar" showRestoreButton="false" showClearButton="true" filterBarExpanded="false"
id="filterBar" clear="filterBarClearBtnPress" />

 

Fetching the variants:
getAllVariants: function(fnCallBack) {
var oPersonalizationVariantSet= {},
aExistingVariants =[],
aVariantKeysAndNames =[];
//get the personalization service of shell
this._oPersonalizationService = sap.ushell.Container.getService('Personalization');
this._oPersonalizationContainer = this._oPersonalizationService.getPersonalizationContainer("MyVariantContainer");
this._oPersonalizationContainer.fail(function() {
// call back function in case of fail
fnCallBack(aExistingVariants);
});
this._oPersonalizationContainer.done(function(oPersonalizationContainer) {
// check if the current variant set exists, If not, add the new variant set to the container
if (!(oPersonalizationContainer.containsVariantSet('MyApplicationVariants'))) {
oPersonalizationContainer.addVariantSet('MyApplicationVariants');
}
// get the variant set
oPersonalizationVariantSet = oPersonalizationContainer.getVariantSet('MyApplicationVariants');
aVariantKeysAndNames = oPersonalizationVariantSet.getVariantNamesAndKeys();
for(var key in aVariantKeysAndNames){
if (aVariantKeysAndNames.hasOwnProperty(key)) {
var oVariantItemObject = {};
oVariantItemObject.VariantKey = aVariantKeysAndNames[key];
oVariantItemObject.VariantName = key;
aExistingVariants.push(oVariantItemObject);
}
}
fnCallBack(aExistingVariants);
}.bind(this));
}

"MyVariantContainer" is the name of the personalization container I used and "MyApplicationVariants" is the name of the personalization variant set.

In the callback function, set the model to variant management control.
 		var oVariantMgmtControl = this.getView().byId("variantManagement"),
// create a new model
oVariantModel = new sap.ui.model.json.JSONModel();
//get Variants from personalization set and set the model of variants list to variant managment control
this.getAllVariants(function(aVariants){
oVariantModel.oData.Variants = aVariants;
oVariantMgmtControl.setModel(oVariantModel);
//enable save button
oVariantMgmtControl.oVariantSave.onAfterRendering = function(){this.setEnabled(true);};
}.bind(this));

Now the existing variants that are present in the variant set will be shown in variant management control.

Generally the save button in the variant management control is disabled. We enabled it by adding

oVariantMgmtControl.oVariantSave.onAfterRendering = function(){this.setEnabled(true);};



Saving the variants:

"onSaveAsVariant" event will be fired on click of "Save" or "Save As".

In the mParameters of event , you see a parameter "overwrite" set to "true" when you click on "Save" i.e. it saves the filters to the selected variant. It is set to false, when you are creating a new variant by clicking on "Save As".

Gather the filter data in the filter bar and now save the variant to the variant set.
onSaveAsVariant: function(oEvent) {
//oSelectedFilterData is the json object with the data seleced in the filter bar
this.saveVariant(oEvent.mParameters.name, oSelectedFilterData, function() {
//Do the required actions
}.bind(this));
}

/**
* This method is to save the variant
* @param {String} sVariantName- Variant name
* @param {Object} oFilterData- Filter data object-> consolidated filters in JSON
* @param {Function} fnCallBack- the call back function with the array of variants
*/
saveVariant: function(sVariantName, oFilterData, fnCallBack) {
// save variants in personalization container
this._oPersonalizationContainer.fail(function() {
// call back function in case of fail
fnCallBack(false);
});
this._oPersonalizationContainer.done(function(oPersonalizationContainer) {
var oPersonalizationVariantSet ={},
oVariant = {},
sVariantKey = "";
// check if the current variant set exists, If not, add the new variant set to the container
if (!(oPersonalizationContainer.containsVariantSet("MyApplicationVariants"))) {
oPersonalizationContainer.addVariantSet('MyApplicationVariants');
}
// get the variant set
oPersonalizationVariantSet = oPersonalizationContainer.getVariantSet('MyApplicationVariants');

//get if the variant exists or add new variant
sVariantKey = oPersonalizationVariantSet.getVariantKeyByName(sVariantName);
if (sVariantKey) {
oVariant = oPersonalizationVariantSet.getVariant(sVariantKey);
} else {
oVariant = oPersonalizationVariantSet.addVariant(sVariantName);
}
if (oFilterData) {
oVariant.setItemValue('Filter', JSON.stringify(oFilterData));
}
oPersonalizationContainer.save().fail(function() {
//call callback fn with false
fnCallBack(false);
}).done(function() {
//call call back with true
fnCallBack(true);
}.bind(this));
}.bind(this));
},

 

Managing the variant:

 

Managing the variants includes updating the name of existing variant or deleting the variant or changing the default variant.

"onManageVariant" event will be fired when you click on "OK " in manage popup.



The event parameters gives the array of deleted variants, array of updated variants, and the default variant.
 onManageVariant: function(oEvent) {
var aDeletedVariants = oEvent.mParameters.deleted,
aRenamedVariants = oEvent.mParameters.renamed,
sNewDefaultVariantKey = oEvent.mParameters.def;
if (aDeletedVariants.length>0) {
this.deleteVariants(aDeletedVariants, function(bDeleted) {
// delete success if bDeleted is true
});
}
if(aRenamedVariants.length>0) {
// get the variants from variant set and rename them in the personalization variant set and then save it.
}
}


deleteVariants: function(aVariantKeys, fnCallback) {
var oPersonalizationVariantSet ={};
this._oPersonalizationContainer.fail(function() {
//handle failure case
});
this._oPersonalizationContainer.done(function(oPersonalizationContainer) {
if (!(oPersonalizationContainer.containsVariantSet("MyApplicationVariants"))) {
oPersonalizationContainer.addVariantSet("MyApplicationVariants");
}
oPersonalizationVariantSet = oPersonalizationContainer.getVariantSet("MyApplicationVariants");
for (var iCount=0; iCount<aVariantKeys.length; iCount++) {
if (aVariantKeys[iCount]) {
oPersonalizationVariantSet.delVariant(aVariantKeys[iCount]);
}
}
oPersonalizationContainer.save().fail(function() {
//handle failure case
fnCallback(false);
}).done(function() {
fnCallback(true);
}.bind(this));
}.bind(this));
}

To set the default variant, you can use a different variants set , I used a property to in the filter to differentiate normal and default variant.

Select Variant:

On clicking on any variant in the variant list, "onSelectVariant" will be fired. Get the variant key and fetch the data in the variant.
onSelectVariant: function(oEvent) {
var sSelectedVariantKey = oEvent.mParameters.key;
if (sSelectedVariantKey) {
this.getVariantFromKey(sSelectedVariantKey, function(oSelectedVariant){
//logic with the data in variant --oSelectedVariant
}.bind(this));
}
}
getVariantFromKey: function(sVariantKey, fnCallback) {
this._oPersonalizationContainer.fail(function() {
// call back function in case of fail
if (fnCallback) {
fnCallback('');
}
});
this._oPersonalizationContainer.done(function(oPersonalizationContainer) {
var oPersonalizationVariantSet ={};
// check if the current variant set exists, If not, add the new variant set to the container
if (!(oPersonalizationContainer.containsVariantSet(Materials.Constants.VARIANT_SET_KEY))) {
oPersonalizationContainer.addVariantSet(Materials.Constants.VARIANT_SET_KEY);
}
// get the variant set
oPersonalizationVariantSet = oPersonalizationContainer.getVariantSet(Materials.Constants.VARIANT_SET_KEY);
fnCallback(oPersonalizationVariantSet.getVariant(sVariantKey));
});
}

**
Enjoy Learning!!!

Thanks..
33 Comments
former_member259572
Participant
0 Kudos

Thank you for providing such a interesting topic…. and i have some doubts in the above code and usage of codes…

  1. “oSelectedFilterData” function is note found in the code.
  2. where to call this function “getAllVariants”,

is it possible to do all the operation without sap,ushell.container???

Former Member
0 Kudos
Hi,

  1. oSelectedFilterData is the filter object(JSON object with filter data) that I am trying to save as a variant .  Sorry for not mentioning it.

  2. getAllVariants can be called when you need the list of variants. It fetches the list of variants and then you can bind to your control.

    Personalization container is shell service, If you do not have shell container, it will save the varaints in cache and they will be cleared when you clear the cache. So not preferable or useful when you do not have a shell .

former_member259572
Participant
0 Kudos

Thank you… is it possible to do the same operation without using shell?? like changing the metadata and saving the same in variant?? or some other idea??

As i'm using gateway to execute my program.. it throws error on this line

showing that "UITable.controller.js:418 Uncaught TypeError: Cannot read property 'Container' of undefined"

thomas_knobloch
Advisor
Advisor
Hi Anjani,

thanks for sharing the information. But how can I determine the filter values from the filter bar?

How can I fill oSelectedFilterData????

Would be nice if you could also share this information.

Thanks and regards, Thomas
former_member266316
Discoverer
0 Kudos
Thanks for sharing Anjani.
Former Member
0 Kudos
Hi Anjani,

Where to define this "MyVariantContainer" ?

And How to fill the oSelectedFilterData ?

 
Former Member
0 Kudos
 

Can somebody please help exact service name in Gateway or the service path ?

/sap/opu/odata/.... ???

Any quick help will be highly appreciated ?
Former Member
0 Kudos
/sap/opu/odata/UI2/INTEROP/PersContainers

 
Former Member
0 Kudos
Hi Sagar,

MyVariantContainer is the personalization container name.The personalization container is initialized when we call the getPersonalizationContainer method of personalization service.
https://sapui5.hana.ondemand.com/1.36.7/#docs/api/symbols/sap.ushell.services.PersonalizationContain...

oSelectedFilterData  holds the string form of the JSON object of the selected filtered values, you can form the json object in a way so that it is easy for you to populate the data in the fields when you read a variant.
Former Member
0 Kudos
Thanks For Reply,

 

So you have used here simple control or Smart Variant Control ?

Can you share the complete document or Controller code as there are many things which I can see missing here.
Former Member
0 Kudos
Yes, Used variant management control in combination with Filter Bar.
As the topic is about variant management, I have not included the whole controller code. Please let me know what you are looking for, Then I can provide the specific code snippet.
0 Kudos
Hi Anjani,

I am using table perso controller for saving the personalization on using shell service.

can u please explain what need to be done while selecting records by calling method  " selectVarianMethod" and changing the the table layout accordingly?
onSelectVariant: function(oEvent) {
var sSelectedVariantKey = oEvent.mParameters.key;
if (sSelectedVariantKey) {
this.getVariantFromKey(sSelectedVariantKey, function(oSelectedVariant){
//logic with the data in variant --oSelectedVariant
}.bind(this));
}
}
getVariantFromKey: function(sVariantKey, fnCallback) {
this._oPersonalizationContainer.fail(function() {
// call back function in case of fail
if (fnCallback) {
fnCallback('');
}
});
this._oPersonalizationContainer.done(function(oPersonalizationContainer) {
var oPersonalizationVariantSet ={};
// check if the current variant set exists, If not, add the new variant set to the container
if (!(oPersonalizationContainer.containsVariantSet(Materials.Constants.VARIANT_SET_KEY))) {
oPersonalizationContainer.addVariantSet(Materials.Constants.VARIANT_SET_KEY);
}
// get the variant set
oPersonalizationVariantSet = oPersonalizationContainer.getVariantSet(Materials.Constants.VARIANT_SET_KEY);
fnCallback(oPersonalizationVariantSet.getVariant(sVariantKey));
});
}

 

Regards

Shadan

 

 
Hi Ajani,

first thank you for sharing this valuable information with us. Is it possible to save the variants global enabling other users to see my variants? If yes could you provide an code snippet ?

 

Best regards

 

Vural
0 Kudos
Thanks a lot for the solution but I think rename variant doesn't work. We do not have a method to rename the variant. Anyone tried renaming the variant?
former_member467269
Discoverer
0 Kudos
How to hide Type and Author columns in Manage Variants pop-up?
former_member190063
Participant
0 Kudos
Hi,

Can we save the "variant" in backend? When User logged in and launch the app, he can see the variants which he had saved last time?  So how is this possible? Do we need to send the variants to backend?
0 Kudos
Hi together,

Nice tutorial

I have a short question: If I want to save a variant as the standard variant it works until I close the app, if I open the App again the standard variant is not there anymore (the first one is selected as standard).

I think I have to save the standard variant somewhere? Does anybody know where or how?


Many Thanks in advanced
Jayakrishnan
Active Participant
0 Kudos
Hi Anjani,

I implemented the logic as per your blog. But now i want to enable this variant management is base on user. How to do that?

I enabled showShare option, but i dont know how to implement?
Jayakrishnan
Active Participant
0 Kudos
Hey Vural,

Have you done it?
0 Kudos
Unfortunately not we now use the smart filter bar to implement the Variant Management.
Jayakrishnan
Active Participant
0 Kudos
Thank you for your response.
ThomasMundt
Participant
0 Kudos
Hi vural ,

We also use SmartFilterBar with VariantManagement. We try to store appstate (selected filter and variant) as tile in Fiori Launchpad.

How can one achieve change of filter values and storing those changes as a new appstate?

As it seems, changing filter values does not result in persisting this new state via INTEROP/GlobalContainers.

Your help is highly appreciated!


 

Hi Anjani,

I followed your blog to implement variant management. Now i facing issue with setting the default variant for application. After setting the default variant from control once application is reload the default vaiant setting to standard vairant not selected variant.

for default variant i wrote the same what have gave.

 

defaultVariant: function (aVariantKeys, fnCallback) {
var oPersonalizationVariantSet = {};
this._oPersonalizationContainer.fail(function () {
//handle failure case
});
this._oPersonalizationContainer.done(function (oPersonalizationContainer) {
if (!(oPersonalizationContainer.containsVariantSet(“MyApplicationVariants”))) {
oPersonalizationContainer.addVariantSet(“MyApplicationVariants”);
}
oPersonalizationVariantSet = oPersonalizationContainer.getVariantSet(“MyApplicationVariants”);

if (aVariantKeys !== “*standard*”) {
oPersonalizationVariantSet.setCurrentVariantKey(aVariantKeys);
} else {
oPersonalizationVariantSet.setCurrentVariantKey(null);
var prod = sap.ui.getCore().byId(“product”);
var plants = sap.ui.getCore().byId(“plants”);
var manufact = sap.ui.getCore().byId(“manufacturing”);
var location = sap.ui.getCore().byId(“location”);
var change = sap.ui.getCore().byId(“change”);
var Submission = sap.ui.getCore().byId(“Submission”);
prod.setSelectedKeys();
plants.setSelectedKeys();
manufact.setSelectedKeys();
location.setSelectedKeys();
change.setSelectedKeys();
Submission.setSelectedKeys();
}
oPersonalizationContainer.save().fail(function () {
//handle failure case
fnCallback(false);
}).done(function () {
fnCallback(true);
}.bind(this));
}.bind(this));
},

 

this is my code wrote

Can you help in this.

Lee3
Active Participant
0 Kudos
Hi Mohammed,

 

did you solved it? I got the same problem.

 

gr

Vo.
0 Kudos
Hey,

Thanks for the informative blog.

 

I am trying to implement this but facing an issue.

sap.ushell.Container is undefined. any idea how to solve this?

 
former_member620231
Participant
0 Kudos

EDIT: It seems that this tutorial uses a deprecated version of personalization container API. getContainer() should be used instead of getPersonalizationContainer() as seen here:

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

Using this, the Variant object now has the method setVariantName.

Note that you have to get the VariantSet object a little different.

Original post:

I know it’s late but for the other people, you can use something like this.

I am aware that modifying a private member is not recommended but I could not find another way.

_renameVariants: function (aRenamedVariants) {
this._oPersonalizationContainer.fail(function () {
// Error handling
}.bind(this));

this._oPersonalizationContainer.done(function (oPersonalizationContainer) {
var oPersonalizationVariantSet = {};
if (!(oPersonalizationContainer.containsVariantSet("MyAppVariants"))) {
oPersonalizationContainer.addVariantSet("MyAppVariants");
}

oPersonalizationVariantSet = oPersonalizationContainer.getVariantSet("MyAppVariants");

aRenamedVariants.forEach(function (oRenamedVariant) {
var oVariant = oPersonalizationVariantSet.getVariant(oRenamedVariant.key);
oVariant._oVariantName = oRenamedVariant.name;
});

oPersonalizationContainer.save().fail(function () {
// Error handling
}.bind(this));
}.bind(this));
},
former_member620231
Participant

Hi,

I know it’s late but for the others, this is what I did.

I set a custom value named Default for every variant. Zero or one of them will have its value equal to true (zero when standard is the default), the rest have the value false.

_setNewDefaultVariantKey: function (sNewDefaultVariantKey) {
this._oPersonalizationContainer.done(function (oPersonalizationContainer) {
var oPersonalizationVariantSet,
oVariant;

if (!(oPersonalizationContainer.containsVariantSet('MyApplicationVariants'))) {
oPersonalizationContainer.addVariantSet('MyApplicationVariants');
}
oPersonalizationVariantSet = oPersonalizationContainer.getVariantSet('MyApplicationVariants');

oVariant = oPersonalizationVariantSet.getVariant(sNewDefaultVariantKey);

oPersonalizationVariantSet.getVariantKeys().forEach(function (sKey) {
oPersonalizationVariantSet.getVariant(sKey).setItemValue("Default", false);
});

if (oVariant) { // It is not the standard one
oVariant.setItemValue("Default", true);
}

oPersonalizationContainer.save().fail(function () {
// Error handling
}.bind(this));
}.bind(this));
}

 

When I save a variant I added:

if (bDefault) {
oPersonalizationVariantSet.getVariantKeys().forEach(function (sKey) {
oPersonalizationVariantSet.getVariant(sKey).setItemValue("Default", false);
});

oVariant.setItemValue("Default", true);
}

Where bDefault = oEvent.getParameter(“def”) at the beginning of the save function.

And in the getAllVariants function I set the default variant for variant management control and also I change the selection to that. Note that setSelectionKey does not work for me but setInitialSelectionKey does.

if (oVariant.getItemValue("Default")) {
this.getView().byId("variantManagement").setDefaultVariantKey(sKey);
this.getView().byId("variantManagement").setInitialSelectionKey(sKey);
}
michael_smithe5
Participant
0 Kudos
Anjani,

Thanks for the information.  How do you populate oSelectedFilterData?  I've tried using the FilterBar object itself for that parameter and FilterBar.getFilterGroupItems(), but neither of those worked.

Thanks,
Michael
0 Kudos

Hi,

Can someone please highlight where and how exactly the second code snippet should be written? I do not quite understand this - "In the callback function, set the model to variant management control"

var oVariantMgmtControl = this.getView().byId("variantManagement"),
// create a new model
oVariantModel = new sap.ui.model.json.JSONModel();
//get Variants from personalization set and set the model of variants list to variant managment control
this.getAllVariants(function(aVariants){
oVariantModel.oData.Variants = aVariants;
oVariantMgmtControl.setModel(oVariantModel);
//enable save button
oVariantMgmtControl.oVariantSave.onAfterRendering = function(){this.setEnabled(true);};
}.bind(this));

Newbie here! Kindly help!!

BR,
Krisha

emil33
Participant
0 Kudos
You need to set showShare property to false as shown belov:
<vm:VariantManagement variantItems="{/VariantList}" select="onSelect" save="onSaveAs" enabled="true" manage="onManage"
showExecuteOnSelection="false" showShare="false" id="Variants">
emil33
Participant
0 Kudos
Hi

This is great solved my default issue.

But I still have a problem with setting the variants public as in using the sharing option to share it with other users.

Do you know how to implement this?
AlexNecula
Active Contributor
Hi Emil,

I ended up using a different implementation with the smart variant management.

You can try following my blog and see if it helps you:

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

Alex
emil33
Participant
0 Kudos
Hi Alex,

Thanks for the response, I have looked at the blog and just needed a clarification on some things, I have posted a question the blog you linked.
If you are able to answer it that would help alot.

Emil
Labels in this area