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

Using UI5 Web Components without any framework

This is a pure “academic” project to get a better understanding of how to use UI5 Web Components without any framework such as React, Angular or Vue.

My goal is to create blog series during which we will cover following topics

  • Getting started with UI5 Web Components
  • Enhancing our example using template tag
  • Let´s create a bundle
  • I hate todo lists, so we create a shopping list example 😉
  • Additional topics such as i18n, theming and create your own UI5 Web Components

Getting started with UI5 Web Components

Get started

This blog is a result of something I hacked together during SAP TechEd 2020. I wanted to get a first understanding how UI5 Web Components work and how I can use them.
The excellent blog post from Marius Obert made me curios but I am not much familiar with React, Angular or Vue. I wanted to keep things simple. I am more a hands-on person (#HandsOnSAPDev), I get an itch to start building stuff once I understand (or think I understand 😉 ) the basic concepts.

What we will do in this first blog is to create simple webapp that will contain a UI5 table and button.
The button will trigger displaying data in our table.

At the end it should look like the table example provided on the official documentation UI5 Web Components Table.

WARNING!
I am using modern JavaScript syntax that might not work with older browsers. Please use a modern browser.

Initializing the project

So let’s get our hands dirty by initializing our project using npm

mkdir ui5-webcomponents-wo-frk
cd ui5-webcomponents-wo-frk
npm init -y

We will create an HTML and a JavaScript file to keep things separate. By things I mean describing the form of the content (HTML) and the actual logic (JavaScript).

Before that we should actually know how we can create a UI5 Web Component. Looking at the official documentation there are two ways to create a UI5 Web Component element

  • Using HTML tags defined by the Web Component
  • Using the HTML DOM API e.g. createElement

Alright, let’s do that and create our HTML file. To speed things up, I copied the table from the official documentation 😉 .

Nothing fancy here. We declare a table and create the columns. No table rows or cells yet to actually display any product data.

<html>

<head>
    <title>UI5 Web Components w/o Framework</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
</head>

<body>
    <div>
        <ui5-table id="productsTable" no-data-text="No Data" show-no-data>
            <ui5-table-column slot="columns" style="width: 12rem">
                <span style="line-height: 1.4rem">Product</span>
            </ui5-table-column>

            <ui5-table-column slot="columns" min-width="800" popin-text="Supplier">
                <span style="line-height: 1.4rem">Supplier</span>
            </ui5-table-column>

            <ui5-table-column slot="columns" min-width="600" popin-text="Dimensions" demand-popin>
                <span style="line-height: 1.4rem">Dimensions</span>
            </ui5-table-column>

            <ui5-table-column slot="columns" min-width="600" popin-text="Weight" demand-popin>
                <span style="line-height: 1.4rem">Weight</span>
            </ui5-table-column>

            <ui5-table-column slot="columns">
                <span style="line-height: 1.4rem">Price</span>
            </ui5-table-column>
        </ui5-table>
    </div>
    
</body>

</html>

Yes we did it! We used the UI5 Web Components successfully in our HTML page. Or did we?

Well we are not there yet. Just because there is a tag does not mean the browser knows what to do with it.
We have to let the browser know the tag and how it should be rendered (UI5 and Fiori style please).

Adding UI5 Web Components Modules

UI5 Web Components are delivered as ES6 Modules. In order to use the modules we actually need to get them.
So we run:

npm install @ui5/webcomponents

Now we have the UI5 Web Components in the `node_modules` folder. Great.

Hmmm, opening the page in your favorite web browser still shows errors in the console.

What we have to achieve that the needed UI5 Web Components are actually loaded. Looking at the documentation we find the following statements.

import "@ui5/webcomponents/dist/Table.js";
import "@ui5/webcomponents/dist/TableColumn.js";

Perfect, now we know what to do but we are still not clear where to put this code.
Reading another tutorial we realize that we have to create a JavaScript file in which we place the import statements.
We want to keep the JavaScript files in a different folder so we create one real quick

mkdir src

We create a new file `index.js` and add the import statements in there. Nothing else.

In addition, we have to load the JavaScript in our HTML document.

<body>
...
</table>
<script type="module" src="./src/index.js"></script>
</body>

 

Finally! We are ready to see our beautiful UI5 table any seconds now…

WHAAAATTTT?

This error tells us we can’t just load js files who are importing ES6 modules when simply opening the html file in a browser.

So we need a local web server to run our UI5 Web Components app. NPM to the rescue!

Using a local web dev server

There a many options to choose from but I found the Web Dev Server and it worked out of the box. That’s all I wanted for now.
Most important is that the imported ES6 modules (which are in the node_modules folder) can be resolved by this web server without the need to involve any bundlers like Webpack, Snowpack, Rollup, Parcel, … . We will take a look at bundlers in a later blog post.

To use it we will install it as a dev dependency

npm i --save-dev @web/dev-server

Let’s edit the package.json file and add an npm command to start the server

"scripts": {
"start": "wds --node-resolve --watch --open"
},

Now all that’s left to do, is to run the command and see the “magic happen”.

npm run start

Jippie, we finally see our empty table 😉 . It seems like a bit of an effort but once you got the basics setup you are prepared for implementing the real thing.

Adding the button to populate data

Ok now we can add some data to our table. As a starter we will load the data from a local .json file (Fetching data from our beloved NorthWind OData Service will be added later)

[
{
"Product": "Notebook Basic 15HT-1000",
"Supplier": "Very Best Screens",
"Dimensions": "30 x 18 x 3cm",
"Weight": "4.2KG",
"Price": "956EUR"
},
{
"Product": "Notebook Basic 17HT-1001",
"Supplier": "Very Best Screens",
"Dimensions": "29 x 17 x 3.1cm",
"Weight": "4.5KG",
"Price": "1249EUR"
},
{
"Product": "Notebook Basic 18HT-1002",
"Supplier": "Very Best Screens",
"Dimensions": "28 x 19 x 2.5cm",
"Weight": "4.2KG",
"Price": "1570EUR"
},
{
"Product": "Notebook Basic 19HT-1003",
"Supplier": "Smartcards",
"Dimensions": "32 x 21 x 4cm",
"Weight": "4.2KG",
"Price": "1650EUR"
},
{
"Product": "ITelO VaultHT-1007",
"Supplier": "Technocom",
"Dimensions": "32 x 22 x 3cm",
"Weight": "0.2KG",
"Price": "299EUR"
},
{
"Product": "Notebook Professional 15HT-1010",
"Supplier": "Very Best Screens",
"Dimensions": "33 x 20 x 3cm",
"Weight": "4.3KG",
"Price": "1999EUR"
},
{
"Product": "Notebook Professional 17HT-1011",
"Supplier": "Very Best Screens",
"Dimensions": "33 x 23 x 2cm",
"Weight": "4.1KG",
"Price": "2299EUR"
},
{
"Product": "ITelO Vault NetHT-1020",
"Supplier": "Technocom",
"Dimensions": "10 x 1.8 x 17cm",
"Weight": "0.16KG",
"Price": "459EUR"
},
{
"Product": "ITelO Vault SATHT-1021",
"Supplier": "Technocom",
"Dimensions": "11 x 1.7 x 18cm",
"Weight": "0.18KG",
"Price": "149EUR"
},
{
"Product": "Comfort EasyHT-1022",
"Supplier": "Technocom",
"Dimensions": "84 x 1.5 x 14cm",
"Weight": "0.2KG",
"Price": "1679EUR"
},
{
"Product": "Comfort SeniorHT-1023",
"Supplier": "Technocom",
"Dimensions": "80 x 1.6 x 13cm",
"Weight": "0.8KG",
"Price": "512EUR"
}
]

Our button to start populating the table with our data is still missing. So let’s add the UI5 Web Components button.
First things first. Let’s import the button and then add the HTML tags.

./src/index.js

import "@ui5/webcomponents/dist/Button";

Inside the index.html we place the button directly underneath the table.

...
    <div>
        <ui5-button id="ui5Button" design="Emphasized">Populate data</ui5-button>
    </div>
...

If we open our browser with the local dev web server session we will now see this

But how do we populate the data once button is clicked? Let’s take a look at the documentation again. If you scroll all the way down you can see the available events for the ui5 button. It also provides a solution how we can bind to the click event.

Now we “just” have to get the ui5 button from the DOM and register an event listener.
Getting elements from the DOM can be done by using methods of the Document Web API.

We will use the powerful querySelector method to get our ui5 button. If you want to learn more about CSS selectors that can be used take a look here.

const ui5Button = document.querySelector('ui5-button')

Before we continue we should check if this actually works. Open our browser with the local dev web server session. Open up the development tools of your browser and run document.querySelector(‘ui5-button’) in the console.

Ok great this works. Now we can continue with adding the event listener.

import "@ui5/webcomponents/dist/Table.js";
import "@ui5/webcomponents/dist/TableColumn.js";
import "@ui5/webcomponents/dist/Button";
import "@ui5/webcomponents/dist/TableRow.js";
import "@ui5/webcomponents/dist/TableCell.js";

const ui5Button = document.querySelector('ui5-button')

ui5Button.addEventListener('click', addData)

async function addData() {
    const response = await fetch('./data/products.json')
    const products = await response.json()

    const table = document.querySelector('ui5-table')

    products.forEach(product => {
        const tableRow = document.createElement('ui5-table-row')

        for (const [key, value] of Object.entries(product)) {
            const tableCell = document.createElement('ui5-table-cell')
            tableCell.innerHTML = value
            tableRow.append(tableCell)
        }
        table.appendChild(tableRow)
    });
}

Ok we actually did a lot of things in just a few lines of code. Let me guide you through

  1. In order to create UI5 Web Components HTML elements we have to import ui5-table-row and ui5-table-cell
  2. We use the Fetch API to load data from our JSON file containing the products.
  3. We have to add the data into the cells of the ui5 table. In order to add anything to the table we need to have access to it first. We use the querySelector method again.
  4. Now comes the interesting part. Just like regular HTML tables the ui5 table has rows and cells. We create a row for each product and a cell for each property of our product object.
  5. We create the ui5-table-row HTML element using the createElement method.
  6. For each property of the product object we create a ui5-table-cell. The cell contains the value of the current products property. At the end we append the cell to the row using ParentNode.append method.

Ok let’s see if our button does what we hope it will do

YAAAAYYYY it actually works :sparkles: :relieved:

Of course this code is not perfect (we do not catch any potential errors, we can click the button multiple times, …) but it works for now.

I am quite happy with the result but there is always a possibility for improvement. We create HTML elements using JavaScript and if we would add more logic we might end up in a mess. ( Peter Muessig pointed that out and provided some tips how to improve the app. Thx again Peter 😉 )

Let’s quickly summarize what we learned on our little journey with UI5 Web Components

  • How to install UI5 Web Components
  • Where we can get additional information about UI5 Web Components
  • How to import the ES6 modules in JavaScript
  • How to load JavaScript files in HTML when ES6 modules are used
  • How to serve a webapp with ES6 modules using a local dev server
  • How to use the HTML DOM API and some other Web APIs
  • How to create UI5 Web Component HTML elements using HTML tags and JavaScript
  • How to register an event listener for a specific event of an html element

Not too bad I would say. We will continue this journey and in the next blog post we will explore a better way how we can create the table using HTML only (almost).

Notes

  • This is my very first blog post on the SAP community. Feel free to provide feedback or ask additional questions. Or just like it in case you enjoyed reading it.
  • Kudos to all SAP community members creating blog posts for the community on a frequent basis. It is quite some work and I highly appreciate what you guys are doing
  • Thx to Peter Muessig and Marco Beier for reviewing my blog post

Related Links

Assigned Tags

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

      A great first post 🥳.
      Thanks, Christian!

      Author's profile photo Marco Beier
      Marco Beier

      Starting out with a banger! Great first post! 🥳

      Author's profile photo Miklos Nemeth
      Miklos Nemeth

      Quite useful example, thank you. I've just cloned your solution and reimplemented it with my toolset of choice: Vite (actually highly recommended on the UI5 getting started document page) as bundler, TypeScript, lit-html as lightning fast reactive DOM updater/builder, Lit Element to make the entire application a series of web components composed of other web components including the excellent UI5 web component library. With these tools you can apply a combination of reactive as well as traditional imperative (MVC/MVVM) programming paradigm. It's really great that SAP realized the potential in web components, and with UI5 web components SAP is on the front end (pun intended).