Skip to Content
Technical Articles

Beyond SAPUI5 and SAP Fiori Elements – Appendix to TechEd Session IIS114

This post is an extension of my session IIS114 during the SAP TechEd Global. This session introduces UI developers to all available options to create SAP Fiori-compliant web interfaces and highlights their differences. The on-demand session can be watched here (and on YouTube), but of course, you can also read this post first and watch the session later. In contrast to the presentation, this post is a little bit heavier on source code and includes web references to the various projects.

Inspecting%20all%20three%20web%20apps%20with%20the%20developer%20tools

While the three web apps look very much alike, you can easily spot the DOM tree differences within the developer tools.

The screenshot above shows three To-Do list applications that come with the same features. I’ve been told that there has been a similar project in the past that compares a bunch of other frameworks with the same approach (Disclaimer: From what I see that code isn’t leveraging the latest version and best practices of the respective frameworks). While they use their own layout for the To-Do app, the technologies of this project will implement SAP Fiori UX. Each of our web apps has input fields to add new items and shows the existing items in two separate lists. The unchecked items are in the upper list and the checked ones in the lower, collapsable list. Items can also be removed and changed via the edit dialog that we will focus on later. These apps look identical because all of them follow the SAP Fiori Design Guidelines. From the standard browser view, you wouldn’t expect that all apps are built with very different technologies:

The left one is built with SAPUI5, the center one with Fundamental React, and the right one with UI5 Web Components for React. These technologies follow different paradigms and have, therefore, also distinct advantages and disadvantages. In the TechEd session, I mostly focus on a conceptual comparison and how much flexibility and reusability the frameworks/libraries offer. In the end, it’s up to the architect to make the following trade-off on a per-project basis:

This post will be less about the conceptual differences and focus more on the different “coding experience.”

SAPUI5 Sample App

The%20gold%20standard%3A%20The%20SAPUI5%20web%20app

The gold standard: An app built with the well-established SAPUI5 framework.

Introduction

SAPUI5 and its open-sourced sibling, OpenUI5, are probably the best knows web technologies in this comparison. Both are commonly referred to as “UI5” and let you build enterprise-ready web applications responsive to all devices, running on almost any browser of your choice. They are based on JavaScript, using jQuery as their foundation, and follow web standards. They ease your development with a client-side HTML5 rendering library, including a rich set of controls, and support data binding to different data models (JSON, XML, and OData).

SAPUI5 uses the well-established Model-View-Controller (MVC) model to separate the project’s code. The models (OData, JSON, and XML) just need to point to a resource, and the framework takes care of the model’s lifecycle via hooks. The view is typically built with XML and combines standard controls, custom controls, and fragments to create an appealing user experience. The framework will render the HTML code based on these views. The various controllers (one per view) take care of the event handling and the navigation of the views. So overall, we can say that the developer’s primary focus is on the orchestration of existing controls and the business logic in the controllers.

Code Review

The edit dialog

Here is a snippet of a dialog view that consists of labels, fields, and buttons. You can also see that the i18n support comes “for free” without any additional work.

<Dialog id="editDialog" title="{i18n>EDIT_TODO}" contentWidth="400px">
  <content >
    <VBox>
      <Label text="{i18n>TODO_TITLE}" labelFor="input-title" />
      <TextArea width="100%" id="input-title" value="{/edit/text}"/>
      <Label text="{i18n>TODO_DATE}" labelFor="input-date" />
      <DatePicker id="input-date" valueFormat="dd/MM/yyyy" displayFormat="dd/MM/yyyy" value="{/edit/deadline}" />
    </VBox>
  </content>
  <buttons >
    <Button text="{i18n>CANCEL}" press=".onClose"/>
    <Button type="Emphasized" text="{i18n>SAVE}" press=".onSave"/>
  </buttons>
</Dialog>

When we want to open the dialog, we need to (a) provide data via the model and (b) call the “open” function. Both can be done from a controller method via event handling.

onEditTodo: function (oEvent) {
	var oModel = this.getView().getModel();
	const todo = oEvent.getSource().getBindingContext().getObject();

	oModel.setProperty("/edit", Object.assign({}, todo));
	this.getView().byId("editDialog").open();
},

UI5 Web Components for React Sample App

The%20web%20standard%3A%20This%20web%20app%20has%20been%20build%20with%20UI5%20Web%20Components

Strictly following web standards: This web app has been build with UI5 Web Components.

Introduction

This sample app leverages the UI5 Web Components, which provide a set of web components that share many methods and properties with well-known SAPUI5 controls. This will help SAPUI5 developers to find their way when getting started with this new technology. UI5 Web Components are neither built on top of UI5, but rather lightweight and independent UI elements nor are they a successor of UI5, but rather a complementary offering. These web components can be used natively or in combination with any web development framework such as AngularReact, and Vue.js.

For React, there is even a separate wrapper implementation around UI5 Web Components, making them even more comfortable. This sample application has been implemented with the UI5 Web Components for React.

Code Review

React apps don’t follow the MVC model but use so-called components. Not to be confused with UI5 Web Components or the web technology web components! These React components are used to divide the code into various files. The philosophy behind this is to have small, light-weight, self-enclosed components that can easily be reused. For this, each component needs to manage its own data (state) and business logic. Larger components delegate parts of that state to their subcomponents. Components are built with a mix of JavaScript (or TypeScript) and XML, so-called JSX. To assemble the edit dialog we’re seen above, we would have to build a dedicated “EditDialog” component with the following snippet:

import { Label } from "@ui5/webcomponents-react/lib/Label";
import { TextArea } from "@ui5/webcomponents-react/lib/TextArea";
import { Dialog } from "@ui5/webcomponents-react/lib/Dialog";
import { Button } from "@ui5/webcomponents-react/lib/Button";
import { DatePicker } from "@ui5/webcomponents-react/lib/DatePicker";

import PropTypes from "prop-types";
import React, { Component, createRef } from "react";

class EditDialog extends Component {

  constructor(props) {
    super(props);
    this.state = {
      id: "",
      text: "",
      deadline: ""
    };
    this.editDialog = createRef();
  }

  open() {
    this.editDialog.current.open();
  }

  onBeforeOpen = () => {
    this.setState({
      id: this.props.todoBeingEditted.id,
      text: this.props.todoBeingEditted.text,
      deadline: this.props.todoBeingEditted.deadline
    });
  }

  handleTextChange = event => {
    this.setState({ text: event.target.value });
  };

  handleDateChange = event => {
    this.setState({ deadline: event.target.value });
  };

  render() {
    return <Dialog header-text="Edit Todo item" ref={this.editDialog} onBeforeOpen={this.onBeforeOpen} >
      <div className="dialog-content">
        <div className="edit-wrapper">
          <Label>Title:</Label>
          <TextArea className="title-textarea" max-length="24" show-exceeded-text value={this.state.text} onChange={this.handleTextChange} ></TextArea>
        </div>

        <div className="edit-wrapper date-edit-fields">
          <Label>Date:</Label>
          <DatePicker format-pattern="dd/MM/yyyy" value={this.state.deadline} onChange={this.handleDateChange} ></DatePicker>
        </div>
      </div>
      <div className="dialog-footer" >
        <Button design="Transparent" onClick={() => { this.editDialog.current.close(); }}>Cancel</Button>
        <Button design="Emphasized" onClick={() => { this.props.saveItem(this.state); this.editDialog.current.close(); }}>Save</Button>
      </div>
    </Dialog>;
  }

}

EditDialog.propTypes = {
  todoBeingEditted: PropTypes.object,
  saveItem: PropTypes.func,
};

export default EditDialog;

We see that the component is self-enclosed and provides an “open” function, which delegates this call to the generic UI5 Web Components Dialog component. Most of the rest of the code takes care of internal state management.

To render this component in a larger component, we need to import it, add it to the render function via JSX, and pass in props:

<EditDialog ref={editDialog} todoBeingEditted={todoBeingEditted} saveItem={handleSave} />

Like the previous example, we need to provide data and call the “open” function to display the dialog. This JSX code is the equivalent of the snippet we saw in the previous section.

 const handleEdit = useCallback((id) => {
    const todoObj = todos.filter(todo => {
      return todo.id === id;
    })[0];

    setTodoBeingEditted(() => ({
      id: id,
      text: todoObj.text,
      deadline: todoObj.deadline
    }));

    editDialog.current.open();
  }, [todos, setTodoBeingEditted]);

Fundamental React Sample App

The%20extendable%3A%20This%20application%20is%20based%20on%20Fundamentals%20Library%20Styles

The extendable: This application is based on Fundamental Library Styles.

Introduction

The sample application leverages the Fundamental Library Styles, which delivers a Fiori 3 component library for building SAP user interfaces with any web technology. Fundamental Library Styles is a light-weight presentation layer that can be used with your UI framework of choice (e.g., AngularReactVue.js, etc.). With this library of stylesheets and HTML tags, developers can build consistent SAP Fiori apps in any web-based technology.

This sample application has been implemented with Fundamental React, which offers a React implementation of the components designed in Fundamental Styles.

Code Review

The following React component is very much like the previous example. The most significant difference is that we have an additional state, showDialog, and import different components (this time from the Fundamental React library). The Fundamental React library leaves it up to us to manage the “visible” state of the dialog components while the UI5 Web Components provided a semantic “open” method.

import { Dialog } from "fundamental-react/lib/Dialog";
import { Button } from "fundamental-react/lib/Button";
import { DatePicker } from "fundamental-react/lib/DatePicker";
import { FormLabel, FormTextarea } from "fundamental-react/lib/Forms";

import PropTypes from "prop-types";
import React, { Component, createRef } from "react";

class EditDialog extends Component {

  constructor(props) {
    super(props);
    this.state = {
      id: "",
      text: "",
      deadline: "",
      showDialog: false
    };
  }

  open() {
    this.setState({
      id: this.props.todoBeingEditted.id,
      text: this.props.todoBeingEditted.text,
      deadline: this.props.todoBeingEditted.deadline,
      showDialog: true
    });
  }

  onBeforeOpen = () => {
    this.setState({
      id: this.props.todoBeingEditted.id,
      text: this.props.todoBeingEditted.text,
      deadline: this.props.todoBeingEditted.deadline
    });
  }

  handleTextChange = event => {
    this.setState({ text: event.target.value });
  };

  handleDateChange = event => {
    this.setState({ deadline: event.formattedDate});
  };

  render() {
    return <Dialog
      actions={[
        (<Button key="cancelBtn" option="transparent" >Cancel</Button>),
        (<Button key="saveBtn" option="emphasized" onClick={() => { this.props.saveItem(this.state); this.setState({ showDialog: false }); }} >Save</Button>)
      ]}
      onClose={() => { this.setState({ showDialog: false }); }}
      show={this.state.showDialog}
      title="Edit Todo item" >
      <div className="dialog-content">
        <div className="edit-wrapper">
          <FormLabel>Title:</FormLabel>
          <FormTextarea  onChange={this.handleTextChange}  defaultValue={this.state.text} />
        </div>

        <div className="edit-wrapper date-edit-fields">
          <FormLabel>Date:</FormLabel>
          <DatePicker
            dateFormat="DD/MM/YYYY"
            className="add-todo-element-width"
            onChange={this.handleDateChange} 
            defaultValue={this.state.deadline} />
        </div>
      </div>
    </Dialog>;
  }
}

EditDialog.propTypes = {
  todoBeingEditted: PropTypes.object,
  saveItem: PropTypes.func,
};

export default EditDialog;

The usage of this edit dialog works in the same way as the previous example.

<EditDialog ref={editDialog} todoBeingEditted={todoBeingEditted} saveItem={handleSave} />

Another difference to the previous example is that the library only brings the SAP Fiori Styles and the component implementations. Some general SAP Fiori resources such as the used fonts and icons need to be imported manually in the project. The easiest option to do this is via CSS and a file-copy-operation in the post-install hook.

@font-face {
  font-family: "72";
  src: url("72-Regular.woff") format("woff");
  font-weight: normal;
  font-style: normal;
}

@font-face {
  font-family: "SAP-icons";
  src: url("SAP-icons.woff") format("woff");
  font-weight: normal;
  font-style: normal;
}
"scripts": {
  ...
  "postinstall": "cp node_modules/@sap-theming/theming-base-content/content/Base/baseLib/sap_fiori_3/fonts/SAP-icons.woff src &&  cp node_modules/@sap-theming/theming-base-content/content/Base/baseLib/sap_base_fiori/fonts/72-Regular.woff src"
},

Number of wrapper libraries

I made a mistake during the session recording, and unfortunately, I noticed it when it was just too late to correct it. I said that there was a wrapping library for Angular, React, and Vue.js for both approaches, but this is not true. There is only a React wrapper for the UI5 Web Components. Which means there are not six but four open-source projects available on GitHub:

Fundamental Library Styles

Fundamental React

Fundamental Angular

Fundamental Vue

UI5 Web Components

UI5 Web Components for React

By the way: These are the official names of the projects. Please apologize if I used slightly different variations in the recording.

Comparison

The following table shows a comparison between the mentioned web technologies. For a further explanation, please check out the source code on GitHub or the associated TechEd Online session IIS114.

Fundamental Library Styles

UI5 Web Components

SAPUI5/OpenUI5

Runtime size of sample app¹

≈1.6MB ≈0.9MB ≈7.6MB

Performance of sample app²

99 100 67

Flexibility

Very high High Moderate

Open standards

High Very high Moderate

Available controls

100+ 80+ 650+

Vendors

>2 >2 1

Compatibility with SAP Fiori launchpad

Decoupled <iframe> Decoupled <iframe> Integrated <iframe>

Maturity

v0.13.0 v0.27.0 v1.84.1

Themeable

SAP Fiori compliant

As of December 2020

¹ Measured with the network inspector of the Google Chrome Dev Tools

² According to the Google Chrome Lighthouse report

Summary

We’ve seen that both React-based applications are the clear winners in the performance comparison as the web apps have a small footprint and load very fast. Their disadvantage is that they have not yet reached a stable release, which means breaking changes could still happen on any minor release. They cannot be integrated as natively in the SAP Fiori Launchpad as SAPUI5 and SAP Fiori Elements apps can. Another advantage of SAPUI5 is that it comes with a broad set of available and well-tested controls that have been working reliably for years. Besides this, SAPUI5 comes with many enterprise-features like i18n support, routing capabilities, theming, adaptability, and OData clients out of the box. This makes the development process as smooth as possible.

 

My personal recommendation for projects that require multiple of the enterprise features that I mentioned above is SAPUI5. This well-aged framework is very stable, and you can be sure that it comes with all you need. The situation looks a little bit different when we’re talking about research-like projects or POCs. SAPUI5 is also well suited for these projects, but the React-based libraries’ advantages could outweigh SAPUI5 here. Using these new frameworks will not only help you to get a beautiful, incredibly responsive user interface, it will also help your developers to broaden their horizons and get to know a new development philosophy and mindset. In the SAP TechEd session IIS114, I’ll talk more about the differences between Fundamental Library Styles and UI5 Web Components.

22 Comments
You must be Logged on to comment or reply to a post.
    • You're welcome, Srdjan.

      I'm not sure if I get that question, what kind of dependencies are you thinking of? The GitHub Repo should show all the node dependencies per app in case you mean these ones (e.g. this one).

      • Yes, I mean external dependencies of:

        Fundamental Library Styles

        Fundamental React

        Fundamental Angular

        Fundamental Vue

        UI5 Web Components

        UI5 Web Components for React

        Frameworks use workspaces/packages and external dependencies (runtime, not devDependencies) are listed in more than one package.json. There are no too many package.json files and I can check by myself, only think the information somehow belongs to your analysis. I am interested how many and which dependencies are used, ideally none. Also if some dependencies are maybe used both by Fundamental and UI5, is SAPUI5 still using jQuery and so on. Dependencies are important aspect to me, probably for some other developers too and the info on that would make your analysis even more complete.

        • Ah, I think I got it now. Yes, that absolutely makes sense. I'm not sure how I would add this to the analysis though.
          I'd say, OpenUI5 apps usually have no runtime dependency. You could argue that CDN that delivers the core libs are a runtime dep but that's something you can work around with the self-contained build.

          I think it's harder for the React-based apps because the apps from above technically don't have any runtime deps. But only because create-react-app adds a bunch of deps via react-scripts and bundles all of them (incl the UI5 Web Components and Fundamental Library Styles) with webpack in one runtime library. So there are no deps left after webpack is done. Of course, React apps can be built without webpack, react-scripts, and even without create-react-app. Then, there would be runtime dependencies that need to be managed otherwise.

          This only covered the case in which we'll use React - Vue.js and Angular could be totally different (I don't know much about these frameworks tbh). So it's really hard to answer this question fully and it would probably end up in a recommendation to use webpack to outsource the problem.

          For this reason, I added the row "Vendors" which basically says that you have one vendor for OpenUI5 apps (namely: SAP) and at least two vendors for all the other options (namely: SAP for the Fiori library and one for the core framework like React).

          Is this answer helpful? If so, I'd link it from the table above.

  • Enterprise-features are mentioned in the text: “like i18n support, routing capabilities, theming, adaptability, and OData clients out of the box”

    Further below, enterprise features are linked to section called Essentials and the term enterprise-features is not mentioned there at all.

    Is there a definition what enterprise features actually are?

    Are these Essentials the “official” list of enterprise-features?

      • There is no clear definition of enterprise features and the Essentials section in DemoKit is not the official list. Still, there is a natural overlap as seen by Srdjan Boskovic: enterprise features are an essential aspect of an Enterprise Framework like SAPUI5.  

        When I try to make it short and crisp, enterprise features are:

        • all runtime/control features that allow to build product standard compliant UIs with display/data entry capabilities as expected by professional users (ACC, i18n, p13n, security, keyboard handling,…)
        • all features that allow to build a large number of highly consistent applications that can be integrated to run business processes cross several apps
        • something like UI5 Flexibility to allow modification free adjustments on several levels
        • a programming model and dev environments to develop these apps highly efficient – means ideally close to low code
        • a clear lifecycle separation of application and framework code to be able to centrally innovate/update/patch 1000s of applications
        • Thanks Stefan Beck . A separate list could be IMHO helpful here, because enterprise-features are taken as the decision criteria for using SAPUI5. "Essentials" like drag-drop for example, look like a different thing to me.

  • Great blog post Marius Obert!

    What do you mean by Compatibility with SAP Fiori launchpad (decoupled vs. integrated).
    What advantages does SAPUI5 offer compared to the other technologies when I integrate an app into the launchpad.

    • Hi Simon,

      good point! I agree that this terminology is somewhat confusing but I couldn't think of a better one.

      The idea is that "integrated" allows the nested app to be aware of the shell bar around it, i.e. it can consume services from the Fiori Launchpad (such as the user service). In the decoupled scenario, the app is not aware that it is embedded.

      I hope this helps.

  • Great post, and very informative.

    I think UI5 greatly suffers by fragmenattion: while might be a smaller issue with http2, it's still serving a silly number of small files.

    Is there any plan to make it work with bundlers, like pretty much any other framework I know of?

    • Hi Marcello,

      thanks for your comment. I think this is already possible today.

      To which files do you refer, only the files of your UI5 app (controllers, views, etc) or of the whole project (including the SAP libs like sap.m, etc)?

      Depending on the files, you need to choose the preload or the self-contained option with the "ui5 build" command.