Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
WouterLemaire
Active Contributor

Introduction


In this blog post series, I’ll show how to create a Web Component and consume it in UI5! This is based on my UI5con session of 2023 together with peter.muessig .

- Vanilla Web Component: https://blogs.sap.com/2023/07/07/ui5con-2023-vanilla-web-component/
- UI5 Web Component (this one): https://blogs.sap.com/2023/07/07/ui5con-2023-ui5-web-component/
- Generate UI5 Library & Controls for UI5 Web Components: https://blogs.sap.com/2023/07/07/ui5con-2023-generate-ui5-library-controls-for-ui5-web-components/
- Consume UI5 Controls based on UI5 Web Components inside a UI5 app: https://blogs.sap.com/2023/07/07/ui5con-2023-consume-ui5-controls-based-on-ui5-web-components-inside...

In the previous blog post, I created a Vanilla Web Component. In this blog post, I will transform the Vanilla Web Component into a UI5 Web Component. This is needed to bring the Web Component into the UI5 framework.



Create package


For creating a UI5 Web Component, we start by creating a UI5 Web Component package:

  • Generate a UI5 WebComponent Package


npm init @ui5/webcomponents-package@latest


  • Provide the name for the package, eg.: spacepackage

  • Select the preferred language, TypeScript

  • Provide the name for the first UI5 WebComponent, eg.: SpaceComponent

  • JSDoc namespace: leave it as it is, this is a placeholder for the namespace of the UI5 library in a later phase.



This will generate a project pre-configured to start developing UI5 Web Components, including a first Web Component. In my case it generated all the files for the SpaceComponent:



SpaceComponent


The generator already came with sample code for the SpaceComponent. Now, I will complete this with the code I already had from my Vanilla Web Component.

  • Provide the template in the SpaceComponent.hbs file: The template is almost exactly the same as for the Vanilla Web Component except it now allows to use handlebar placeholders for the attributes. This time, I provide a placeholder for intro and logo


<div class="star-wars-intro">
<p class="intro-text">{{intro}}</p>

<h2 class="main-logo">
<img src="{{logo}}"/>
</h2>

<div class="main-content">
<div class="title-content">
<slot></slot>
</div>
</div>
</div>

Full template code: https://github.com/lemaiwo/ui5-space-webcomponent-package/blob/main/src/SpaceComponent.hbs

  • In the SpaceComponent.ts file, include the dependency for slots which needed to use the @slot annotation


import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";


  • Define the properties in the SpaceComponent class: the properties have the same names that are being used in the template.

    • Small remark, the JSDoc is very important for later to create the UI5 control out of the UI5 Web Component




	/**
* Defines the intro of the space component.
*
* @type {string}
* @name demo.components.SpaceComponent.prototype.intro
* @defaultvalue ""
* @public
*/
@property()
intro!: string;

/**
* Defines the logo of the space component.
*
* @type {string}
* @name demo.components.SpaceComponent.prototype.logo
* @defaultvalue ""
* @public
*/
@property()
logo!: string;


  • Next to the properties, define the slot: the slot is defined as the default slot as this is the only one and I would like to use this in UI5 for the default aggregation


	/**
* Defines the articles of the component.
*
* @type {demo.components.SpaceItemComponent[]}
* @name demo.components.SpaceComponent.prototype.default
* @slot items
* @public
*/
@slot({ type: HTMLElement, "default": true })
items!: Array<SpaceItemComponent>;


  • Implement the logic for generating the stars using onAfterRendering function: this is a lifecycle function of UI5 Web Components and can be compared to onAfterRendering in UI5 views and controls.


onAfterRendering() {
const numStars = 100;
const mainDiv = this.shadowRoot!.querySelector(".star-wars-intro") as HTMLElement;

// For every star we want to display
for (let i = 0; i < numStars; i++) {
const { top, left } = this.getRandomPosition(mainDiv);
mainDiv.append(this.getRandomStar(top, left));
}
}
getRandomStar(top: string, left: string) {
const star = document.createElement("div");
star.className = "star";
star.style.top = top;
star.style.left = left;
return star;
}
getRandomPosition(element: HTMLElement) {
return {
top: `${this.getRandomNumber(element.offsetHeight)}px`,
left: `${this.getRandomNumber(element.offsetWidth)}px`,
};
}
getRandomNumber(value: number) {
return Math.floor(Math.random() * value);
}

 

Full code for the SpaceComponent class: https://github.com/lemaiwo/ui5-space-webcomponent-package/blob/main/src/SpaceComponent.ts

Finally add the css style to the SpaceComponent.ts from here: https://github.com/lemaiwo/ui5-space-webcomponent-package/blob/main/src/themes/SpaceComponent.css

 

SpaceItemComponent


Once the SpaceComponent is created we can start creating the second one which will behave as a child: “SpaceItemComponent”. This can be done by the following steps:

  • Create a new component for the items: SpaceItemComponent


npm run create-ui5-element




  • Include it in the bundle.esm.js


import "./dist/SpaceItemComponent.js";


  • Provide the template in SpaceItemComponent.hbs


<article class="space-article">
<h2>{{title}}</h2>
<p>{{description}}</p>
</article>

Code for the template: https://github.com/lemaiwo/ui5-space-webcomponent-package/blob/main/src/SpaceItemComponent.hbs

  • Provide the class for the SpaceItemComponent: this only contains two properties, not much additional


import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
import { getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
import property from "@ui5/webcomponents-base/dist/decorators/property.js";

// Template
import SpaceItemComponentTemplate from "./generated/templates/SpaceItemComponentTemplate.lit.js";

// Styles
import SpaceItemComponentCss from "./generated/themes/SpaceItemComponent.css.js";

/**
* @class
*
* <h3 class="comment-api-title">Overview</h3>
*
*
* <h3>Usage</h3>
*
* For the <code>ui5-space-item-component</code>
* <h3>ES6 Module Import</h3>
*
* <code>import SpacePackage/dist/SpaceItemComponent.js";</code>
*
* @constructor
* @alias demo.components.SpaceItemComponent
* @extends sap.ui.webc.base.UI5Element
* @tagname space-item-component
* @public
*/
@customElement({
tag: "space-item-component",
renderer: litRender,
styles: SpaceItemComponentCss,
template: SpaceItemComponentTemplate,
})
class SpaceItemComponent extends UI5Element {
/**
* Defines the title of the space item component.
*
* @type {string}
* @name demo.components.SpaceItemComponent.prototype.title
* @defaultvalue ""
* @public
*/
@property()
title!: string;

/**
* Defines the description of the space item component.
*
* @type {string}
* @name demo.components.SpaceItemComponent.prototype.description
* @defaultvalue ""
* @public
*/
@property()
description!: string;
}

SpaceItemComponent.define();

export default SpaceItemComponent;

Full code of the SpaceItemComponent class: https://github.com/lemaiwo/ui5-space-webcomponent-package/blob/main/src/SpaceItemComponent.ts

  • Provide css


.space-article>h2 {
text-align: center;
}

Css code: https://github.com/lemaiwo/ui5-space-webcomponent-package/blob/main/src/themes/SpaceItemComponent.cs...

  • Resolve dependency in SpaceComponent for SpaceItemComponent


import SpaceItemComponent from "./SpaceItemComponent.js";

 

Build Web Component package


Both UI5 Web Components are created, now it is time to build the UI5 Web Component package.

Run  the command: “npm run build”

This will make a build of the Web Components in the package which is required for generating the UI5 controls. The start command executes similar steps but not all of them. Therefore it is important to run the build as well.

 

Test Web Component package


The UI5 Web Components can be tested directly in the package from the index.html page in the test folder. To do this we need to provide an example in the test page “test/pages/index.html”
<space-component id="myFirstComponent" intro="Hello UI5con!" logo="./img/star-wars-intro.png">
<space-item-component title="EPISODES IV-VI" description="After years of galactic silence, civilization is on the brink of a new Star Wars release. Now, with the Force preparing to awaken, the people of Earth seek solace in films of old. With nowhere to turn, they gather in great numbers and watch the original trilogy without rest. Three films. 6 hours. 24 minutes. Popcorn. Slushies. Total elation."></space-item-component>
<space-item-component title="Episode V: The Empire Strikes Back Opener" description="It is a dark time for the Rebellion. Although the Death Star has been destroyed, Imperial troops have driven the Rebel forces from their hidden base and pursued them across the galaxy.Evading the dreaded Imperial Starfleet, a group of freedom fighters led by Luke Skywalker has established a new secret base on the remote ice world of Hoth.The evil lord Darth Vader, obsessed with finding young Skywalker, has dispatched thousands of remote probes into the far reaches of space"></space-item-component>
</space-component>

Full example of the test page: https://github.com/lemaiwo/ui5-space-webcomponent-package/blob/main/test/pages/index.html

npm start

This will run the test page with the UI5 Web Component in it. It is a little bit small but you can already test if it works:


The test page allows you to test in different themes and languages.

Full project is available on GitHub: https://github.com/lemaiwo/ui5-space-webcomponent-package/tree/main

Clone it, build it and run it with “npm i” and “npm start”.

With that we have converted the Vanilla Web Component to a UI5 Web Component. The first step and biggest one to bring the Space Web Component to UI5.

 

 

 
Labels in this area