1

UI5con 2023 – UI5 Web Component

 10 months ago
source link: https://blogs.sap.com/2023/07/07/ui5con-2023-ui5-web-component/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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-a-ui5-app/

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.

image1-2.png

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.
image2-2.png

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:

image3-4.png

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
image4-3.png
  • 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.css

  • 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:

image5-2.png

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.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK