Skip to Content
Technical Articles
Author's profile photo Christian Sosa

How to embed two Fiori Elements List Reports into one Freestyle SAPUI5 App

The Fiori Elements Framework offers two solutions to display information in two different tabs within a single List Report: ‘Multiple Views'[1] and the ‘Flexible Programming Model'[2]. However, to use Multiple Views, there must be a common data source (CDS View in most cases) and the Flexible Programming Model is only available for OData v4. This article describes an alternative approach to overcome this limitation.

Requirement

An App is needed to display two Fiori Elements (FE) List Reports alongside each other within a single SAPUI5 Freestyle App. Those List Reports were built with OData v2 and each one consumes a different CDS View in the backend.

Solution

Starting point

You have developed and deployed two FE Apps to the on Premise BSP Library of an R3 or S/4HANA system. Our two demo apps are:

List Report A

  • Component ID: zlistreporta
  • ICF node: /sap/bc/ui5_ui5/demo/zlistreporta

List Report B

  • Component ID: zlistreportb
  • ICF node: /sap/bc/ui5_ui5/demo/zlistreportb

You can find more information about developing FE Apps here[3].

Create a new Fiori Freestyle App with a single view

You can use a wizard of your choice to generate a blank app and deploy it.

Main App (container for both List Reports)

  • Component ID: zmainapp
  • ICF node: /sap/bc/ui5_ui5/demo/zmainapp

Declare the List Reports A and B within the main App’s Component.js

sap.ui.define([
	"sap/ui/core/UIComponent",
	"sap/ui/Device",
	"zcustomer/zmainapp/model/models"
], function (UIComponent, Device, models) {
	"use strict";

	return UIComponent.extend("zcustomer.zmainapp.Component", {

		metadata: {
			manifest: "json"
		},

		/**
		 * The component is initialized by UI5 automatically during the startup of the app and calls the init method once.
		 * @public
		 * @override
		 */
		init: function () {
			// call the base component's init function
			UIComponent.prototype.init.apply(this, arguments);

			// enable routing
			this.getRouter().initialize();

			// set the device model
			this.setModel(models.createDeviceModel(), "device");
			
			// register child applications
			jQuery.sap.registerModulePath("zlistreporta", "/sap/bc/ui5_ui5/sap/zcustomer/zlistreporta");
			jQuery.sap.registerModulePath("zlistreportb", "/sap/bc/ui5_ui5/sap/zcustomer/zlistreporta");
		}
	});
});

Alternatively, the components may be referenced within the main App’s manifest.json as recommended here[4].

Reference the Components within the view XML code

<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" controllerName="zcustomer.zmainapp.controller.View1" displayBlock="true">
	<Shell id="shell">
		<App id="app">
			<pages>
				<Page id="page" title="{i18n>title}">
					<content>
						<IconTabBar selectedKey="filter1" stretchContentHeight="true">
							<items>
								<IconTabFilter text="FE List Report A" id="filter1">
									<content>
										<sap.ui.core:ComponentContainer height="100%" name="zlistreporta"/>
									</content>
								</IconTabFilter>
								<IconTabFilter text="FE List Report B" id="filter2">
									<content>
										<sap.ui.core:ComponentContainer height="100%" name="zlistreportb"/>
									</content>
								</IconTabFilter>
							</items>
						</IconTabBar>
					</content>
				</Page>
			</pages>
		</App>
	</Shell>
</mvc:View>

The following points are essential for the app to work:

  • A Shell container must be a direct child of the view element and contain all other elements.
  • The IconTabBar must be configured with stretchContentHeight=”true”, so that the componentContainers are visible.
  • Both componentContainer elements must be created within the <content> aggregation of each IconTabFilter. Otherwise they will not get rendered.

Deploy the Main App and check results

The results can only be tested once the App has been deployed. Testing within the WebIDE should also be possible, but further configuration is needed.

Tipps and Tricks

  • Disabling build before deploy: with Apps generated by WebIDE, running a whole build of the App may take a couple of minutes, which is not desirable during development, when deployment is done frequently. Performing a Build before deploying can be deactivated by editing ui5.yaml. A quick-and-dirty workaround is renaming the file to -ui5.yaml’ (or any other name) during development.
  • Testing without deploying should be possible but is beyond the scope of this article.
  • Empty caches if modifications are not directly shown after deploy: Because of this deployment mechanism, applying changes to the underlying Fiori Elements Apps does not always automatically impact on the resulting Main App. For those cases, clearing caches is necessary.

Caveats

  • The Main App cannot be directly tested directly through the WebIDE.
  • The FE Apps might require a Shell Configuration. In this case, make sure that the Main SAPUI5 App has a sap.m.Shell control containing both the FE Apps. The example discussed on this article contemplates this (see Line 2 of the XML file)
  • When developing with external Components, the errors shown on the browser’s debugger console are generally not very helpful. Therefore development must be carried out step by step and paying close attention to network errors. The debugger console should at least load the external component along with the app under development. Should this not be the case, then the Component cannot be found either because of a wrong path or namespace.

Benefits

  • Increase usability: If our business case requires two Fiori Elements Apps to be displayed together, it is only practical to bundle them together in a single App.
  • Simplify Launchpad configuration:┬áSince we can now display two Fiori Elements Apps within a single Fiori tile, we are saving one Fiori Tile and one Target Definition. Nevertheless a BSP-App and a ui5 ICF-Node are still needed.
  • Accelerate development of Freestyle Apps: We could have arrived at the same result by developing a completely Freestyle App with an icon tab bar, two smart filter bars and two smart tables. This would have required much more development. We used the Fiori Elements framework instead to leverage on the backend annotations within our CDS Views.

References

Bonus

So far ChatGPT does not provide an accurate answer to “How can I embed two Fiori Elements Apps into one Fiori Freestyle App”, because it only offered a solution by using cross-application navigation. Here’s the output: https://pastebin.com/NYXeaL5C

Assigned Tags

      3 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Ravish Garg
      Ravish Garg

      Interesting application! However, if the two FE reports relate to same business context, isn't a multi tab FE report better suited? Like documented here - https://ui5.sap.com/#/topic/a37df408044e41ef84e67207c8658d4f

      If there is no common context, then anyways doesn't make sense to combine two reports into a single tile.

       

      Regards

      R

      Author's profile photo Christian Sosa
      Christian Sosa
      Blog Post Author

      Hello Ravish, thanks for your feedback! You are right, I just added the link you provided and a clarification paragraph to the beginning of the article.

      The reason why I could not use a multi tab FE List Report was that I did not have a single data source behind both reports. Each had its own CDS-View underneath, with different columns as well. These were also part of an existing development and users found it cumbersome to constantly have to go to the Fiori Launchpad to switch between related applications.

      Many thanks again and kind regards,

      Christian

      Author's profile photo Ravish Garg
      Ravish Garg

      Hi Christian

      The multi tab FE List Report caters to multiple CDS view sources as well! I have used this multiple times now, and the only gotcha to lookout for is that the filterbar can derive the filter fields from the "primary" entity only. Other than that, if your CDS views are in same business context, its a pretty good solution.

       

      Ravish