Skip to Content

In this post you will learn how to add P13N dialog to sap.m.List by using some external classes. 

Introduction:

Have you ever worked with smart tables in SAPUI5? One of the reasons that we use SmartTable is its power in reducing the amount of the code that we must write to achieve the same results as the SmartTable can provide for us.

For example it can read the names of the columns from the annotation files or from the metadata file of the desired OData service. But we believe the most useful and valuable feature of the sap.ui.comp.smarttable.SmartTable is the personalization dialog (which is known as P13N). P13N dialog gives the power of sorting, filtering, grouping of the data and reordering the columns of a table. Here is an example of the smart table with its P13N dialog.

Unfortunately by the time that we are writing this post, there is no smart list available yet. It means if someone needs to have a P13N dialog beside of a list of type sap.m.List in his or her SAPUI5 application, they have to write some codes for the dialog and some codes to act regarding the user changes.

Last year we had a big project with several applications and we needed to copy and past the codes regarding P13N dialog in all of our Master-Details applications. And of course it was not a simple copy and past, we needed to customize the code for each list and do some changes based on desired OData set. This was the point that we tried to have a class to bring the power of the P13N dialog beside of any sap.m.List instance.

We generated two classes for this purpose, ListManager.js and P13nManager.js. We recently published these 2 classes with a working sample via GitHub. By using these two classes you don’t need to write any codes for creating P13N dialog. You just need to create an instance object from the ListManager class and pass desired parameters and objects. Then sit back and enjoy your P13N dialog, fully functional with your list. Before explaining the code, and go more in depth, I invite you to visit the following video to know more about the functionality of the P13N dialog and how it acts.

 

Main Part:

In the rest of the this post we will explain for you how to run the sample code and how to use these two classes inside of your own Master-Details projects. We will not explain the codes of these two classes. Maybe later we provide another post and explain the codes inside of themselves but the aim of this post is to explain you how to use these two classes to add P13N dialog to your own lists especially in Master-Details applications

First of all, let us speak regarding who to run the sample code.

For running the sample code from the GitHub you need to establish a connection to the NorthWind OData service. For establishing the connection please do the steps explained in the following post:

 

https://blogs.sap.com/2014/07/07/how-to-use-northwind-odata-service-with-sap-river-rde/

 

The steps that explained in the refereed post with title “How to use Northwind OData service with SAP Web IDE” can lead to a successful connection creation and accessing to NorthWind OData service in your SAPUI5 applications with a paid account. If you are using a trial account you must do a little bit more. We explained how to run applications which consume NorthWind OData service in trial accounts in the following post:

 

https://blogs.sap.com/2018/10/11/how-to-use-northwind-odata-service-with-sap-web-ide-with-trial-account/

 

Anyway, until now you have to be able to creating a Master-Details application in your WEB IDE and represent data of one of the NorthWind sets. If you have not yet get success please review those two posts again, otherwise without a NorthWind connection you cannot run the sample code.

Now its the time to download the sample code from GitHub and import it in your WEB IDE Workspace. Simply run the application as a web application or run the index.html file. It must show you something like what we can see in the video. Play a little with its P13N dialog and see how does it effect the items inside of your list. Please note as sap.m.List class does not have any column we hided the column panel from our P13N dialog.

We hope you could run the sample code successfully and get familiar with functionality of the P13N dialog. But how can we add it to other SAPUI5 applications? Here we go to explain how to add this functionality to other SAPUI5 Master-Details applications.

 

Firs of all you need to copy and past the two classes (i.e. ListManager.js and P13NManager.js) inside of the controller folder of your project. You can access the copy of these two classes via the GitHub, but we copied the code here as well, as a secure archive.

1. Code for ListManager.js:

/*
@FileName: ListManager.js
@Auther: Mahdi Jaberzadeh Ansari 
@license: MIT Licence 
*/
sap.ui.define([
	"sap/ui/base/Object",
	"./P13nManager"
], function(BaseObject, P13nManager) {
	"use strict";
	return BaseObject.extend("mjzsoft.sapui5.tutorial.controller.ListManager", {
		/*_oP13nManagerSettings: {
			bAddNoneItem: false,
			oI18nIds: {
				sColumnsPanelTitleId: "",
				sSortPanelTitleId: "",
				sFilterPanelTitleId: "",
				sGroupPanelTitleId: "",
				sNoneItemId: ""
			},
			aFilterItems: [{
				sColumnKey: "",
				sColumnI18nKey: ""
			}],
			aSortItems: [{
				sColumnKey: "",
				sColumnI18nKey: ""
			}],
			aGroupItems: [{
				sColumnKey: "",
				sColumnI18nKey: "",
				fnVGroup: null
			}],
			aFilters: [{ // https://sapui5.hana.ondemand.com/1.38.16/#docs/api/symbols/sap.m.P13nFilterItem.html#constructor
				sColumnKey: "",
				sOperation: "Contains",
				sValue1: "0",
				sValue2: "",
				sExclude: false
			}],
			aSort: [{ // https://sapui5.hana.ondemand.com/1.38.16/#docs/api/symbols/sap.m.P13nSortItem.html#constructor
				sColumnKey: "",
				sOperation: "Descending"
			}],
			aGroup: [{ // https://sapui5.hana.ondemand.com/1.38.16/#docs/api/symbols/sap.m.P13nGroupItem.html#constructor
				sColumnKey: "",
				sOperation: "Ascending",
				bShowIfGrouped: true
			}]
		},*/
		constructor: function(oOwnerComponent, oList, oP13NBtn, mP13nSettings) {
			this._oOwnerComponent = oOwnerComponent;
			this._oList = oList;
			this._oP13nManagerSettings = mP13nSettings;
			this._sP13nModel = "__jsonModel_list_" + new Date().getTime();
			this._oListFilterState = {
				aFilters: [],
				aSorter: []
			}; 
			this._initP13NModel();
			this._initP13nDialog();
			oP13NBtn.attachPress(this._openP13nDialog, this);
		},
		_initP13NModel: function() {
			if (this._oP13nManagerSettings) {
				var aNoneItem = [];
				if (this._oP13nManagerSettings.bAddNoneItem === true) {
					aNoneItem.push({
						sColumnKey: null,
						sColumnI18nKey: this._oP13nManagerSettings.oI18nIds.sNoneItemId
					});
				}
				var aColumnsItems = this._oP13nManagerSettings.aColumnItems,
					aFilterItems = aNoneItem.concat(this._oP13nManagerSettings.aFilterItems),
					aSortItems = aNoneItem.concat(this._oP13nManagerSettings.aSortItems),
					aGroupItems = aNoneItem.concat(this._oP13nManagerSettings.aGroupItems);
				this._oP13nModel = new sap.ui.model.json.JSONModel({
					ColumnsItems: aColumnsItems,
					FiltersItems: aFilterItems,
					SortItems: aSortItems,
					GroupItems: aGroupItems,
					Filters: this._oP13nManagerSettings.aFilters,
					Sort: this._oP13nManagerSettings.aSort,
					Group: this._oP13nManagerSettings.aGroup
				});
				this._oOwnerComponent.setModel(this._oP13nModel, this._sP13nModel);
			}
		},
		_initP13nDialog: function() {
			if (this._oP13nManagerSettings) {
				var oP13nSettings = {
					sModel: this._sP13nModel,
					oFiltersItemsBindingInfo: {
						path: this._sP13nModel + ">/FiltersItems"
					},
					oFiltersBindingInfo: {
						path: this._sP13nModel + ">/Filters"
					},
					oSortItemsBindingInfo: {
						path: this._sP13nModel + ">/SortItems"
					},
					oSortBindingInfo: {
						path: this._sP13nModel + ">/Sort"
					},
					oGroupItemsBindingInfo: {
						path: this._sP13nModel + ">/GroupItems"
					},
					oGroupBindingInfo: {
						path: this._sP13nModel + ">/Group"
					},
					fnOnOkButtonPress: this._onP13nDialogOkButtonPress.bind(this),
					oI18nIds: this._oP13nManagerSettings.oI18nIds,
					oPanelsVisibility: {
						bColumn: false,
						bSort: true,
						bFilter: true,
						bGroup: true
					}
				};
				this._oP13nDialog = new P13nManager(this._oOwnerComponent, oP13nSettings, this._oP13nManagerSettings.oListener);
			}
		},
		_onP13nDialogOkButtonPress: function(oEvent) {
			var aP13nSorter = this._oP13nDialog.getSorter();
			var aP13nFilter = this._oP13nDialog.getFilter();
			var aP13nGroup = this._oP13nDialog.getGroup();
			var aFilters = [];
			var aSorter = [];
			if (aP13nGroup) {
				for (var iGroupIndex = 0; iGroupIndex < aP13nGroup.length; ++iGroupIndex) {
					aSorter.push(aP13nGroup[iGroupIndex]);
				}
			}
			if (aP13nSorter) {
				for (var iSorterIndex = 0; iSorterIndex < aP13nSorter.length; ++iSorterIndex) {
					aSorter.push(aP13nSorter[iSorterIndex]);
				}
			}
			if (aP13nFilter) {
				for (var iFilterIndex = 0; iFilterIndex < aP13nFilter.length; ++iFilterIndex) {
					aFilters.push(aP13nFilter[iFilterIndex]);
				}
			}
			this._oListFilterState.aFilters = aFilters;
			this._oListFilterState.aSorter = aSorter;
			this._applyGroupSort();
			this._applyFilterSearch();
		},
		_openP13nDialog: function() {
			if (this._oP13nDialog) {
				this._oP13nDialog.open();
			}
		},
		_applyFilterSearch: function(fnCallBack) {
			var aFilters = this._oListFilterState.aFilters;
			if (typeof fnCallBack === "function") {
				var fnDataReceived = function(oEvent) {
					fnCallBack(oEvent);
					this._oList.getBinding("items").detachDataReceived(fnDataReceived, this);
				}.bind(this);
				this._oList.getBinding("items").attachDataReceived(fnDataReceived, this);
			}
			this._oList.getBinding("items").filter(aFilters, "Application");
		},
		_applyGroupSort: function() {
			var aSorters = this._oListFilterState.aSorter;
			this._oList.getBinding("items").sort(aSorters);
		}
	});

});

 

2. Code for P13nManager.js:

/*
@FileName: P13nManager.js
@Auther: Mahdi Jaberzadeh Ansari 
@license: MIT License 
*/
sap.ui.define([
	"sap/ui/base/Object",
	"sap/ui/model/Sorter",
	"sap/ui/model/Filter",
	"sap/ui/model/FilterOperator",
	"sap/ui/model/json/JSONModel",
	"sap/m/P13nGroupPanel",
	"sap/m/P13nGroupItem"
], function(BaseObject, Sorter, Filter, FilterOperator, JSONModel, P13nGroupPanel, P13nGroupItem) {
	"use strict";
	return BaseObject.extend("mjzsoft.sapui5.tutorial.controller.P13nManager", {
		// The following 2 objects just show the structure of input 
		/*mSettings: {
			sModel: "",
			oColumnBindingInfo: {
				path: ""
			},
			oFiltersItemsBindingInfo: {
				path: ""
			},
			oFiltersBindingInfo: {
				path: ""
			},
			oSortItemsBindingInfo: {
				path: ""
			},
			oSortBindingInfo: {
				path: ""
			},
			oGroupItemsBindingInfo: {
				path: ""
			},
			oGroupBindingInfo: {
				path: ""
			},
			fnOnOkButtonPress: null,
			oI18nIds: {
				sColumnsPanelTitleId: "",
				sSortPanelTitleId: "",
				sFilterPanelTitleId: "",
				sGroupPanelTitleId: ""
			},
			oPanelsVisibility: {
				bColumn: true,
				bSort: true,
				bFilter: true,
				bGroup: true
			}
		},*/
		constructor: function(oOwnerComponent, mSettings, oListener) {
			this._oOwnerComponent = oOwnerComponent;
			this._oP13nManagerSettings = mSettings;
			this._oListener = oListener;
			this._iRandId = null;
			this._oPersonalizationDialog = null;
			this._oColumnsPanel = null;
			this._oSortPanel = null;
			this._oFilterPanel = null;
			this._oGroupPanel = null;
			this._aColumnsItems = [];
			this._aFilterItems = [];
			this._aSortItems = [];
			this._aGroupItems = [];
			this._init();
		},
		_init: function() {
			this._iRandId = new Date().getTime();
			var oData = this._oOwnerComponent.getModel(this._oP13nManagerSettings.sModel).getData();
			for (var iColumnIndex = 0; oData.ColumnsItems && iColumnIndex < oData.ColumnsItems.length; ++iColumnIndex) {
				this._aColumnsItems[iColumnIndex] = oData.ColumnsItems[iColumnIndex];
				this._aColumnsItems[iColumnIndex].iIndex = iColumnIndex;
			}
		},
		getRandId: function() {
			return this._iRandId;
		},
		onP13nDialogOkButtonPress: function(oEvent) {
			if (typeof this._oP13nManagerSettings.fnOnOkButtonPress === "function") {
				this._oP13nManagerSettings.fnOnOkButtonPress(oEvent);
			}
			this._oPersonalizationDialog.close();
		},
		onP13nDialogCancelButtonPress: function(oEvent) {
			if (typeof this._oP13nManagerSettings.fnOnCancelButtonPress === "function") {
				this._oP13nManagerSettings.fnOnCancelButtonPress(oEvent);
			}
			this._oPersonalizationDialog.close();
		},
		onP13nDialogResetButtonPress: function(oEvent) {
			if (typeof this._oP13nManagerSettings.fnOnResetButtonPress === "function") {
				this._oP13nManagerSettings.fnOnResetButtonPress(oEvent);
			}
		},
		open: function() {
			var oPersonalizationDialog = this._getDialog();
			oPersonalizationDialog.setShowResetEnabled(this.bShowResetEnabled);
			oPersonalizationDialog.open();
		},
		getFilter: function() {
			var aFilterItems = this._oFilterPanel.getFilterItems(),
				aFilters = [];
			for (var i = 0; i < aFilterItems.length; i++) {
				var sPath = aFilterItems[i].getColumnKey(),
					bExclude = aFilterItems[i].getExclude(),
					sOperation = bExclude === true ? sap.ui.model.FilterOperator.NE : aFilterItems[i].getOperation(),
					sValue1 = aFilterItems[i].getValue1(),
					sValue2 = aFilterItems[i].getValue2();
				aFilters.push(new Filter({
					path: sPath,
					operator: sOperation,
					value1: sValue1,
					value2: sValue2
				}));
			}
			return aFilters;
		},
		getSorter: function() {
			var aSortItems = this._oSortPanel.getSortItems(),
				aSorters = [];
			for (var i = 0; i < aSortItems.length; i++) {
				var bDescending = aSortItems[i].getOperation() === "Descending" ? true : false,
					sPath = aSortItems[i].getColumnKey();
				aSorters.push(new Sorter(sPath, bDescending, false));
			}
			return aSorters;
		},
		getGroup: function() {
			var aGroupItems = this._oGroupPanel.getGroupItems(),
				aSorters = [];
			for (var i = 0; i < aGroupItems.length; i++) {
				var aCustomData = aGroupItems[i].getCustomData(),
					vGroup = true;
				if (aCustomData.length > 0) {
					if (aCustomData[0].getKey() === "fnVGroup") {
						vGroup = aCustomData[0].getValue();
					}
				}
				aSorters.push(new Sorter(aGroupItems[i].getColumnKey(), false, vGroup));
			}
			return aSorters;
		},
		_getDialog: function() {
			if (this._oPersonalizationDialog) {
				return this._oPersonalizationDialog;
			}
			// associate controller with the fragment
			this._oPersonalizationDialog = this._createP13nDialog();
			this._oListener.getView().addDependent(this._oPersonalizationDialog);
			return this._oPersonalizationDialog;
		},
		_createP13nDialog: function() {
			var aPanels = [];
			if (this._oP13nManagerSettings.oPanelsVisibility.bColumn === true) {
				aPanels.push(this._createP13nColumnsPanel());
			}
			if (this._oP13nManagerSettings.oPanelsVisibility.bSort === true) {
				aPanels.push(this._createP13nSortPanel());
			}
			if (this._oP13nManagerSettings.oPanelsVisibility.bFilter === true) {
				aPanels.push(this._createP13nFilterPanel());
			}
			if (this._oP13nManagerSettings.oPanelsVisibility.bGroup === true) {
				aPanels.push(this._createP13nGroupPanel());
			}

			var oDialog = new sap.m.P13nDialog("__p13nDialog_" + this.getRandId(), {
				panels: aPanels,
				ok: [this.onP13nDialogOkButtonPress, this],
				cancel: [this.onP13nDialogCancelButtonPress, this],
				reset: [this.onP13nDialogResetButtonPress, this]
			});
			return oDialog;
		},
		_createP13nColumnsPanel: function() {
			this._oColumnsPanel = new sap.m.P13nColumnsPanel();
			this._oColumnsPanel.setProperty("title", "{i18n>" + this._oP13nManagerSettings.oI18nIds.sColumnsPanelTitleId + "}");
			this._oColumnsPanel.bindItems({
				path: this._oP13nManagerSettings.oColumnBindingInfo.path,
				factory: this._createP13nItemFactory.bind(this)
			});
			this._oColumnsPanel.bindColumnsItems({
				path: this._oP13nManagerSettings.oColumnBindingInfo.path,
				factory: this._createP13nColumnsItemFactory.bind(this)
			});
			return this._oColumnsPanel;
		},
		_createP13nSortPanel: function() {
			this._oSortPanel = new sap.m.P13nSortPanel();
			this._oSortPanel.setProperty("title", "{i18n>" + this._oP13nManagerSettings.oI18nIds.sSortPanelTitleId + "}");
			this._oSortPanel.attachAddSortItem(this._onAddSortItem, this);
			this._oSortPanel.attachRemoveSortItem(this._onRemoveSortItem, this);
			this._oSortPanel.attachUpdateSortItem(this._onUpdateSortItem, this);
			this._oSortPanel.bindItems({
				path: this._oP13nManagerSettings.oSortItemsBindingInfo.path,
				factory: this._createP13nItemFactory.bind(this)
			});
			this._oSortPanel.bindSortItems({
				path: this._oP13nManagerSettings.oSortBindingInfo.path,
				factory: this._createP13nSortItemFactory.bind(this)
			});
			return this._oSortPanel;
		},
		_createP13nFilterPanel: function() {
			this._oFilterPanel = new sap.m.P13nFilterPanel();
			this._oFilterPanel.setProperty("title", "{i18n>" + this._oP13nManagerSettings.oI18nIds.sFilterPanelTitleId + "}");
			var aIncludeOperations = this._oFilterPanel.getIncludeOperations();
			aIncludeOperations = aIncludeOperations.concat([sap.m.P13nConditionOperation.Contains]);
			this._oFilterPanel.setIncludeOperations(aIncludeOperations);
			this._oFilterPanel.attachAddFilterItem(this._onAddFilterItem, this);
			this._oFilterPanel.attachRemoveFilterItem(this._onRemoveFilterItem, this);
			this._oFilterPanel.attachUpdateFilterItem(this._onUpdateFilterItem, this);
			this._oFilterPanel.bindItems({
				path: this._oP13nManagerSettings.oFiltersItemsBindingInfo.path,
				factory: this._createP13nItemFactory.bind(this)
			});
			this._oFilterPanel.bindFilterItems({
				path: this._oP13nManagerSettings.oFiltersBindingInfo.path,
				factory: this._createP13nFilterItemFactory.bind(this)
			});
			return this._oFilterPanel;
		},
		_createP13nGroupPanel: function() {
			this._oGroupPanel = new P13nGroupPanel();
			this._oGroupPanel.setProperty("title", "{i18n>" + this._oP13nManagerSettings.oI18nIds.sGroupPanelTitleId + "}");
			this._oGroupPanel.bindItems({
				path: this._oP13nManagerSettings.oGroupItemsBindingInfo.path,
				factory: this._createP13nItemFactory.bind(this)
			});
			this._oGroupPanel.bindGroupItems({
				path: this._oP13nManagerSettings.oGroupBindingInfo.path,
				factory: this._createP13nGroupItemFactory.bind(this)
			});
			this._oGroupPanel.attachAddGroupItem(this._onAddGroupItem, this);
			this._oGroupPanel.attachRemoveGroupItem(this._onRemoveGroupItem, this);
			this._oGroupPanel.attachUpdateGroupItem(this._onUpdateGroupItem, this);
			return this._oGroupPanel;
		},
		_createP13nColumnsItemFactory: function(sId, oContext) {
			var oColumnsItem = new sap.m.P13nColumnsItem({
				columnKey: oContext.getProperty("sColumnKey")
			});
			oColumnsItem.bindProperty("visible", {
				model: this._oP13nManagerSettings.sModel,
				path: oContext.getPath() + "/sColumnVisible"
			});
			oColumnsItem.bindProperty("index", {
				model: this._oP13nManagerSettings.sModel,
				path: oContext.getPath() + "/iIndex"
			});
			return oColumnsItem;
		},
		_createP13nSortItemFactory: function(sId, oContext) {
			var oSortItem = new sap.m.P13nSortItem({
				columnKey: oContext.getProperty("sColumnKey"),
				operation: oContext.getProperty("sOperation")
			});
			var sConditionId = "condition_" + sId.split(/\-/).pop();
			this._aSortItems[sConditionId] = oSortItem;
			return oSortItem;
		},
		_createP13nFilterItemFactory: function(sId, oContext) {
			var oFilterItem = new sap.m.P13nFilterItem({
				columnKey: oContext.getProperty("sColumnKey"),
				operation: oContext.getProperty("sOperation"),
				value1: oContext.getProperty("sValue1"),
				value2: oContext.getProperty("sValue2"),
				exclude: oContext.getProperty("bExclude")
			});
			var sConditionId = "condition_" + sId.split(/\-/).pop();
			this._aFilterItems[sConditionId] = oFilterItem;
			return oFilterItem;
		},
		_createP13nGroupItemFactory: function(sId, oContext) {
			var oGroupItem = new sap.m.P13nGroupItem({
				columnKey: oContext.getProperty("sColumnKey"),
				operation: oContext.getProperty("sOperation"),
				showIfGrouped: oContext.getProperty("bShowIfGrouped")
			});
			var sConditionId = "condition_" + sId.split(/\-/).pop();
			this._aGroupItems[sConditionId] = oGroupItem;
			return oGroupItem;
		},
		_createP13nItemFactory: function(sId, oContext) {
			var oItem = new sap.m.P13nItem({
				columnKey: oContext.getProperty("sColumnKey")
			});
			oItem.bindProperty("visible", {
				model: this._oP13nManagerSettings.sModel,
				path: oContext.getPath() + "/bColumnVisible"
			});
			oItem.addCustomData(new sap.ui.core.CustomData({
				key: "fn",
				value: "1"
			}));
			oItem.setProperty("text", "{i18n>" + oContext.getProperty("sColumnI18nKey") + "}");
			return oItem;
		},
		_onAddFilterItem: function(oEvent) {
			var oFilterPanel = oEvent.getSource(),
				oParameters = oEvent.getParameters(),
				oFilterItem = oEvent.getParameter("filterItemData");
			oFilterPanel.addFilterItem(oFilterItem);
			this._aFilterItems[oParameters.key] = oFilterItem;
		},
		_onRemoveFilterItem: function(oEvent) {
			var oFilterPanel = oEvent.getSource(),
				oParameters = oEvent.getParameters();
			oFilterPanel.removeFilterItem(this._aFilterItems[oParameters.key]);
			delete this._aFilterItems[oParameters.key];
		},
		_onUpdateFilterItem: function(oEvent) {
			var oFilterPanel = oEvent.getSource(),
				oParameters = oEvent.getParameters(),
				oFilterItem = oEvent.getParameter("filterItemData");
			var aFilterItems = oFilterPanel.getFilterItems();
			for (var i = 0; i < aFilterItems.length; i++) {
				if (aFilterItems[i] === this._aFilterItems[oParameters.key]) {
					break;
				}
			}
			oFilterPanel.removeFilterItem(this._aFilterItems[oParameters.key]);
			oFilterPanel.insertFilterItem(oFilterItem, i);
			this._aFilterItems[oParameters.key] = oFilterItem;
		},
		_onAddSortItem: function(oEvent) {
			var oSortPanel = oEvent.getSource(),
				oParameters = oEvent.getParameters(),
				oSortItem = oEvent.getParameter("sortItemData");
			oSortPanel.addSortItem(oSortItem);
			this._aSortItems[oParameters.key] = oSortItem;
		},
		_onRemoveSortItem: function(oEvent) {
			var oSortPanel = oEvent.getSource(),
				oParameters = oEvent.getParameters();
			oSortPanel.removeSortItem(this._aSortItems[oParameters.key]);
			delete this._aSortItems[oParameters.key];
		},
		_onUpdateSortItem: function(oEvent) {
			var oSortPanel = oEvent.getSource(),
				oParameters = oEvent.getParameters(),
				oSortItem = oEvent.getParameter("sortItemData");
			var aSortItems = oSortPanel.getSortItems();
			for (var i = 0; i < aSortItems.length; i++) {
				if (aSortItems[i] === this._aSortItems[oParameters.key]) {
					break;
				}
			}
			oSortPanel.removeSortItem(this._aSortItems[oParameters.key]);
			oSortPanel.insertSortItem(oSortItem, i);
			this._aSortItems[oParameters.key] = oSortItem;
		},
		_onAddGroupItem: function(oEvent) {
			var oGroupPanel = oEvent.getSource(),
				oParameters = oEvent.getParameters(),
				oGroupItem = oEvent.getParameter("groupItemData"),
				oList = oGroupPanel.getBinding("items").oList,
				sKey = oGroupItem.getColumnKey();
			oGroupItem.removeAllCustomData();
			for (var i = 0; i < oList.length; i++) {
				if (oList[i].sColumnKey === sKey) {
					if (oList[i].fnVGroup) {
						oGroupItem.addCustomData(new sap.ui.core.CustomData({
							key: "fnVGroup",
							value: oList[i].fnVGroup
						}));
					} else {
						var sText = oList[i].sColumnI18nKey;
						oGroupItem.addCustomData(new sap.ui.core.CustomData({
							key: "fnVGroup",
							value: function(oContext) {
								var sName = oContext.getProperty(sKey);
								return {
									key: sName,
									text: "{i18n>" + sText + "}: " + sName
								};
							}
						}));
					}
					break;
				}
			}
			oGroupPanel.addGroupItem(oGroupItem);
			this._aGroupItems[oParameters.key] = oGroupItem;
		},
		_onRemoveGroupItem: function(oEvent) {
			var oGroupPanel = oEvent.getSource(),
				oParameters = oEvent.getParameters();
			oGroupPanel.removeGroupItem(this._aGroupItems[oParameters.key]);
			delete this._aGroupItems[oParameters.key];
		},
		_onUpdateGroupItem: function(oEvent) {
			var oGroupPanel = oEvent.getSource(),
				oParameters = oEvent.getParameters(),
				oGroupItem = oEvent.getParameter("groupItemData"),
				oList = oGroupPanel.getBinding("items").oList,
				sKey = oGroupItem.getColumnKey();
			oGroupItem.removeAllCustomData();
			for (var i = 0; i < oList.length; i++) {
				if (oList[i].sColumnKey === sKey) {
					if (oList[i].fnVGroup) {
						oGroupItem.addCustomData(new sap.ui.core.CustomData({
							key: "fnVGroup",
							value: oList[i].fnVGroup
						}));
					} else {
						var sText = oList[i].sColumnI18nKey;
						oGroupItem.addCustomData(new sap.ui.core.CustomData({
							key: "fnVGroup",
							value: function(oContext) {
								var sName = oContext.getProperty(sKey);
								return {
									key: sName,
									text: "{i18n>" + sText + "} : " + sName
								};
							}
						}));
					}
					break;
				}
			}
			var aGroupItems = oGroupPanel.getGroupItems();
			for (i = 0; i < aGroupItems.length; i++) {
				if (aGroupItems[i] === this._aGroupItems[oParameters.key]) {
					break;
				}
			}
			oGroupPanel.removeGroupItem(this._aGroupItems[oParameters.key]);
			oGroupPanel.insertGroupItem(oGroupItem, i);
			this._aGroupItems[oParameters.key] = oGroupItem;
		}
	});
});

 

Then you need to add a button on the top of your list. Something like this figure:

 

 

For this purpose we normally provide a toolbar with a button inside of that. Please find your List tag in the Master.view.xml file and change the code like the following:

 

<semantic:MasterPage id="page" title="{masterView>/title}" navButtonPress="onNavBack" showNavButton="true">
	<semantic:subHeader>
		<Toolbar id="headerBar">
			<SearchField id="searchField" showRefreshButton="{= !${device>/support/touch} }" tooltip="{i18n>masterSearchTooltip}" width="100%" search="onSearch"/>
			<Button id="__button_P13N" icon="sap-icon://settings" enabled="{masterView>/p13nEnabled}"/>
		</Toolbar>
	</semantic:subHeader>
	<semantic:content>
		<PullToRefresh id="pullToRefresh" visible="{device>/support/touch}" refresh="onRefresh"/>
			<List id="list" <!-- Rest of the code -->

Normally in auto generated code there is sap.m.Bar in the subHeader tag. We changed it to a Toolbar and added a Button as well. We pass a reference to this button to our ListManager later, so the id of this button is important.

Now it is the time to use our classes in our controller. Open the Master.controller.js file and add a reference to the ListManager class in its header part. Something like this:

sap.ui.define([
	"mjzsoft/sapui5/tutorial/controller/BaseController",
	"sap/ui/model/json/JSONModel",
	"sap/ui/model/Filter",
	...
	"mjzsoft/sapui5/tutorial/controller/ListManager"
], function (BaseController, JSONModel, Filter, ...., ListManager) {

Please note that you have to change the “mjzsoft/sapui5/tutorial/controller/” inside of the address to some suitable path equivalent to your own namespace, or simply use “./ListManager” instead when both files are places at the same folder.

Add the following variables in your i18n.properties file, the last two variables may change based on your use case:

#~~~ P13N Dialog ~~~~~~~~~~~~~~~~~~~~~~~

#XFLD: 
SortPanelTitle=Sort
 
#XFLD: 
FilterPanelTitle=Filter
 
#XFLD: 
GroupPanelTitle=Group
 
#XFLD: 
None=None
 
#XFLD: 
CategoryID=Category ID
 
#XFLD: 
CategoryName=Category Name

 

Now add the following function after your onInit function. Please note the comments inside of the following piece of code. This is the only place that you have to do modifications based on your use case and based on the names of the attributes in your OData set.

initP13N: function (oList) {
	this._oP13nManagerSettings = {
		oListener: this,                       
		bAddNoneItem: false, // To add (None) in the dropdown list or not
		oI18nIds: { // We added these variables to our i18n file
			sSortPanelTitleId: "SortPanelTitle",   
			sFilterPanelTitleId: "FilterPanelTitle",
			sGroupPanelTitleId: "GroupPanelTitle",
			sNoneItemId: "None"
		},
		// items of the filter drop down 
		aFilterItems: [{
			sColumnKey: "CategoryID",
			sColumnI18nKey: "CategoryID"
		}, {
			sColumnKey: "CategoryName",
			sColumnI18nKey: "CategoryName"
		}],
		// items of the sort drop down 
		aSortItems: [{
			sColumnKey: "CategoryID",
			sColumnI18nKey: "CategoryID"
		}, {
			sColumnKey: "CategoryName",
			sColumnI18nKey: "CategoryName"
		}],
		// items of the group drop down
		aGroupItems: [{
			sColumnKey: "CategoryID",
			sColumnI18nKey: "CategoryID",
			// a function to generate group header
			fnVGroup: function (oContext) {
				var sName = "" + oContext.getProperty("CategoryID");
				return {
					key: sName,
					text: "{i18n>" + "CategoryID" + "}: " + sName.replace(/^[0]+/g, "")
				};
			}.bind(this)
		}, {
			sColumnKey: "CategoryName",
			sColumnI18nKey: "CategoryName"
		}],
		// if you have some initial filter, sort or grouping pass them here please 
		aFilters: [],
		aSort: [{
			sColumnKey: "CategoryName",
			sOperation: "Ascending"
		}],
		aGroup: []
	};
	// create an instance object from the ListManager class 
	var oListManager = new ListManager(
		this.getOwnerComponent(),  // A refrence to owner component to sharing the models between classes  
		this._oList, // reference to the list
		this.byId("__button_P13N"), // reference to the button that we created 
		this._oP13nManagerSettings // we created this object recently 
	);
},

 

The last part of the puzzle is to call our initP13N function as soon as our list bound successfully. For this purpose please modify the onInit function. Find “oList.attachEventOnce” inside of the onInit function and modify it like the following:

 

oList.attachEventOnce("updateFinished", function (oEvent) {
	// Restore original busy indicator delay for the list
	oViewModel.setProperty("/delay", iOriginalBusyDelay);
	this.initP13N(oEvent.getSource());
}.bind(this));

Conclusion:

We saw how to add P13N dialog to our sap.m.List instances by using two external class “ListManager.js” and “P13nManager.js“. By this method you don’t nead to write tones of codes for adding P13N to your projects and few lines of codes you can have P13N in your Master-Details applications. I hope you find this post useful, please don’t hesitate to leave your comments and of course you will not forget to like, share and follow us.

Thanks 4 reading.

To report this post you need to login first.

1 Comment

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

Leave a Reply