Skip to Content
Technical Articles
Author's profile photo Emanuel Affatati

SAP Fiori Elements – Initial Filter values

Hello everyone,

As you may know, most of the gaps gathered during FitGap sessions in an S/4HANA project, can be solved using Fiori Elements. SAP Fiori Elements have several templates available that can help us covered most of business requirements. Some of these templates are List Report, Analytical List Report, Overview Pages, Object Pages. You can refer to this link if you want to know more about these templates.

Most of the applications built using these templates (List Report, ALP, Overview pages), generally contains a Filter bar at the top, which we can use it to filter the values shown in the tables or graphics the application may have.

These filter bar is rendered using the Smart Filter Bar component. All the filters that appear in this bar, should be previously defined as Filters using the UI Annotation UI.SelectionFields either in the Core Data Service or a local annotation file.

When building fiori applications using these templates, there is a common requirement that is to add Initial values to the filters provided by the applications. This requirement can be solved in two different ways:

  • The first way is by using S/4HANA user default values. This is the best way to do it, because you can achieve it by using only configurations that have to be made in the fiori catalogs. This process is clearly explained in the following article written by Jocelyn Dart.
  • In case the process to populate these filters could not be achieved by using the User default values, we have the possibility to use javascript logic. Some possible use cases where this method should be chosen, could be if you have to populate the filters with values from other systems, if the values to be set should be processed with some complex logic or if the initial values should be read from an external Identity Provider (i.e. SAML Attributes).

In this blog, I am going to explain how to populate filters with initial data using the second approach previously mentioned.

Fiori Application Extension

In order to be able to add javascript logic to a fiori application, you need a controller file. So the first step is to add a Controller to the project.

You can achieve this by creating the controller folder and file manually, and then adding it to the manifest file, or you can do it in an easier way using the extension wizard as I am going to explain next.

First, right click on the project folder, and select: New > Extension

After selecting the extension button from the menu, a pop up will appear with different extension options depending on the Floorplan you are using. In this case I am going to select Analytical List Page, but you should select the Floorplan that you are currently using in your project.

Then you have to select the kind of extension you are going to execute. In this case, we need to add a Controller to our application, so we are going to select “Action”.

The name you defined in the “Action Label” is not important, because in this case we are going to delete it afterwards.

Finally, you have to confirm your selections, and the wizard will take care of creating the necessary files automatically.

Adapt Manifest.json file

Once you have finished with the wizard, you will see that a new folder named “ext” was created.

This folder contains the controller file as we are going to see later, but first, let’s go to the manifest.json file.

Here you are going to find under the “extensions” object, the configuration of the controller and the action that has been created by the wizard.

As we mentioned at the beginning of this blog, we are only going to need the controller, so we are going to remove all the unnecessary information from the manifest file.

Below you can find how you manifest.json “extensions” object should look like after removing all the unnecessary information.

 

Controllers logic

Once we have finished with the modifications in the manifest.json, we are going to move to the controllers file. This is the file where we are going to allocate the logic we want to apply to our filters.

The controller file is located under the folders “ext > controller” that were created automatically by the wizard.

This file will have by default an empty method, created to handle the action you defined in the wizard. As we are not going to use that method, we can remove it.

Then, we are going to add the standard method onInitSmartFilterBarExtension. This method is executed just before the smart table is rendered for the first time, so it is the right place to write the logic to set the initial value to the filter. All the values set to the filters in this method, are going to be used to filter the information that is going to be shown in the smart table. We are going to set the values in the Smart Filter bar using the standard methods this controller has available as explained here.

In this particular case, I am going to set a filter value of type range, but you can also add single values to a filter.

onInitSmartFilterBarExtension: function (oEvent) {
	//Get SmartFilterBar 
	var oGlobalFilter = oEvent.getSource();

	//Create JSON data that contains the Inital value of the filter
	var lowValue = new Date(new Date().getFullYear(), 0, 1);
	var oToday = new Date();
	//"created_on" is the name of the filter field. You should put your own field ID.
	var oDefaultFilter = {
		"created_on": {
			"ranges": [{
				"exclude": false,
				"operation": "BT",
				"keyField": "created_on",
				"value1": lowValue,
				"value2": oToday
			}]
		}
	};

	//Set SmartFilterBar initial values
	oGlobalFilter.setFilterData(oDefaultFilter);
	
	//In case you want to hide a Filter
	oGlobalFilter.determineFilterItemByName("company_code").setVisibleInFilterBar(false);
}			

As I mentioned previously, in case you want to setup a single value to a filter, you could use for example the following logic:

onInitSmartFilterBarExtension: function (oEvent) {
		//Get SmartFilterBar
		var oGlobalFilter = this.getView().byId("<your SmartFilterBar ID>--template::SmartFilterBar"
		);

		//Create JSON data that contains the Inital value of the filter
		//"company_code" is the name of the filter field. You should put your own field ID.
		var oDefaultFilter = {
			"company_code": "Test"
		};

		//Set SmartFilterBar initial values
		oGlobalFilter.setFilterData(oDefaultFilter);
}

And if you would like to setup both values at the same time, you could also achieve that by using the following code:

onInitSmartFilterBarExtension: function (oEvent) {
		//Get SmartFilterBar 
		var oGlobalFilter = this.getView().byId("<your SmartFilterBar ID>--template::SmartFilterBar"
		);

		//Create JSON data that contains the Inital values of the filters
		var lowValue = new Date(new Date().getFullYear(), 0, 1);
		var oToday = new Date();
		//"company_code" and "created_on" are the names of the filter bar fields. You should put your own field IDs.
		var oDefaultFilter = {
			"company_code": "Test",
			"created_on": {
				"ranges": [{
					"exclude": false,
					"operation": "BT",
					"keyField": "created_on",
					"value1": lowValue,
					"value2": oToday
				}]
			}
		};

		//Set SmartFilterBar initial values
		oGlobalFilter.setFilterData(oDefaultFilter);
}

Below you can see how the code looks like in the WebIde editor.

 

Finally, we are going to execute the application to see how it looks like.

As you can see, when running the report we get the selection field “Created On” populated with the values defined in the controller.

There is other event available where you can setup filter values. It is the method OnBeforeRebindTableExtension. This method is executed before the smart table is rendered each time the report is run, so it can be used to populate, for example, the values of a filter that needs to have a static value through the different report executions. Since this filter is going to have a static value, it could be a great idea to hide it from the user, but that is the content of another blog.

Free Style apps

In case you are building a free style app, you have to use a different event to populate filter with initial values. You have to add the parameter “initialise” and give a function name that you have already created in the app controller.

<smartFilterBar:SmartFilterBar id="smartFilterBar" persistencyKey="UniqueAndStablePersistencyKey" entitySet="DisptabSet" filterBarExpanded="true" enableBasicSearch="true" showClearButton="true" initialise="onInitSmartFilterBar">
</smartFilterBar:SmartFilterBar>

Then, on the app controller, you have to define the functions with the needed logic.

Have in mind that if you don’t the add liveMode=”true” property in the smartfilterbar definition, the GO button is shown but the table/graphs are not automatically rendered.

You have to make them render again in the onInitSmartFilterBar method.

onInitSmartFilterBar: function (oEvent) {
	var currentYear = new Date().getFullYear();
	var oGlobalFilter = this.getView().byId("smartFilterBar");
	var oDefaultFilter = {
		"Year": currentYear
	};
	oGlobalFilter.setFilterData(oDefaultFilter);
	var that = this;
	oGlobalFilter.addContent(new sap.m.Button({
		text: "Show Table",
		press: function () {
			that.onDefaultDialogPress();
		}
	}));
        //These lines refresh the tables/charts you have in your fiori app
	this.getView().byId("smartChart1").rebindChart();
	this.getView().byId("smartTable1").rebindTable();
},

onDefaultDialogPress: function () {
	if (!this.oDefaultDialog) {
		//Dialog Creation
		this.oDefaultDialog = new Dialog({
			title: "Exchange Rates",
			closed: function (oEvent) {
				oEvent.getSource().destroy();
			}
		});

		//To get access to the controller's model
		this.getView().addDependent(this.oDefaultDialog);
		//If you don't want to use the previous statement, you can assign the model to the table
		/*
		var oModel = this.getOwnerComponent().getModel("myModel");
		oTable.setModel(oModel);
		*/
		//Create Table
		var oTable = new sap.m.Table("idPobList", {
			//headerText: "Example",
			inset: true
		});
		//Column Headers
		var col1 = new sap.m.Column("col1", {
			header: new sap.m.Label({
				text: "Column 1 Label"
			})
		});
		oTable.addColumn(col1);
		var col2 = new sap.m.Column("col2", {
			header: new sap.m.Label({
				text: "Column 2 Label"
			})
		});
		oTable.addColumn(col2);
		//Table binding
		var colItems = new sap.m.ColumnListItem("colItems", {
			type: "Active"
		});
		oTable.bindAggregation("items", "/oDataEntitySet", colItems);
		//Cells
		var txtNAME = new sap.m.Text("txtNAME1", {
			text: "{Field1}"
		});
		colItems.addCell(txtNAME);
		var txtNAME2 = new sap.m.Text("txtNAME2", {
			text: "{Field2}"
		});
		colItems.addCell(txtNAME2);

		//Dialog Buttons
		var that = this;
		this.oDefaultDialog.addButton(new sap.m.Button({
			text: "Close",
			press: function () {
				that.oDefaultDialog.close();
			}
		}));
		this.oDefaultDialog.addContent(oTable);
	}

	this.oDefaultDialog.open();
}

 

Well I hope this blog is useful for you.

Thanks.

Best regards,

Emanuel Affatati

Assigned Tags

      7 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Mio Yasutake
      Mio Yasutake

      Thanks for sharing this.

      This is what I've been looking for!

      Author's profile photo Mio Yasutake
      Mio Yasutake

      I have implemented the extension.

      I noticed that onBeforeRebindTableExtension is called each time I press 'Go' button.

      Even if I select different values on the filter, pressing 'Go' overwrites my selection.

      Maybe onInitSmartFilterBarExtension is more suitable hook for setting default values.

      Author's profile photo Emanuel Affatati
      Emanuel Affatati
      Blog Post Author

      Hello Mio,

      Thank you very much for your comments. You are completely right, the most suitable method to populate initial values to the filters would be onInitSmartFilterBarExtension. I have added your suggestions to the blog.

      onBeforeRebindTableExtension is useful when you need a static value in a filter, which was the case of my requirement. I have left the explanation at the end of the blog.

      Thanks.

      Best regards,

      Emanuel

       

      Author's profile photo Gottfried Bleiziffer
      Gottfried Bleiziffer

      Hello Emanuel Affatati,

       

      very nice blog!

      I have a question about the SmartFilterBar ID.

      "<your SmartFilterBar ID>--template::SmartFilterBar"

      Where can i find my SmartFilterBar ID? I searched for it on all pages but I can't find it.

      It would be very nice if you can help me.

      Thanks.

      Best regards,

      Gottfried

      Author's profile photo Emanuel Affatati
      Emanuel Affatati
      Blog Post Author

      Hello Gottfried,
      You can get it using the UI5 Inspector Chrome plugin.
      Or in a simpler way, you can get it using the following statement as I have shown in the first snippet of code.

      //Get SmartFilterBar 
      	var oGlobalFilter = oEvent.getSource();

      Hope this helps.

      Best regards,

      Emanuel

      Author's profile photo JAVIER RUBIO
      JAVIER RUBIO

      Hello Emanuel,

      To enhance a Fiori elements List filter bar, instead of defining fixed values i am pulling them from backend using below code:

       

      The problem is that now the main entity is not being called when hitting Go button, as it has been replaced by the entity used in the filter enhancement ( /CompanycodeListSet ).

      Do you know how can i solve this issue, please?

      Thanks,

      Javier

      Author's profile photo SAGAR SINGH
      SAGAR SINGH

      Hi Emanuel Affatati

      Instead of populating the search field with token at the start of application, I want to give input token inside application and then retrieve the token data of search fields of smart filter bar from extended controller.

      If I input the date inside 'Created On' search filed, how can I get that filter token data inside the

      onBeforeRebindTableExtension function of extended controller, as it is called every time I press GO.

      Thanks.

      Best regards,

      Sagar Singh