Loading Audio...
Deploying Clarity's Ticket List Custom Element
Clarity needs an application that allows distributors to view, filter, and expand their open and in-progress tickets. Clarity’s development team is familiar with the React framework and prefers to use it in their frontend implementations. With Liferay’s plug-and-play capabilities, they can continue using React without compromising Liferay’s updates or upgrades.
In this exercise, you’ll explore and deploy a React application developed by Clarity’s team as a custom element client extension to retrieve, filter, and display ticket data.
- 
	
Open a file explorer and navigate to the
exercises/module-1/folder in your course workspace. - 
	
Rename the
react-app/folder toclarity-ticketing-ui.
This is our application folder, which we will transform into a client extension. - 
	
Open the
clarity-ticketing-ui/webpack.config.jsfile and paste the following code./** * SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com * SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06 */ const path = require('path'); const webpack = require('webpack'); const DEVELOPMENT = process.env.NODE_ENV === 'development'; const WEBPACK_SERVE = !!process.env.WEBPACK_SERVE; module.exports = { devServer: { headers: { 'Access-Control-Allow-Origin': '*', }, port: 3000, }, devtool: DEVELOPMENT ? 'source-map' : false, entry: { index: './index.js', }, externals: { 'react': 'react', 'react-dom': 'react-dom', }, experiments: { outputModule: true, }, mode: DEVELOPMENT ? 'development' : 'production', module: { rules: [ { test: /\.(js|jsx)$/, // Process .js and .jsx files exclude: /node_modules/, // Exclude dependencies use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env', '@babel/preset-react'], }, }, }, { test: /\.css$/, // Process .css files use: ['style-loader', 'css-loader'], }, ], }, resolve: { extensions: ['.js', '.jsx'], // Add .jsx to extensions }, optimization: { minimize: !DEVELOPMENT, }, output: { clean: true, environment: { dynamicImport: true, module: true, }, filename: WEBPACK_SERVE ? '[name].js' : '[name].[contenthash].js', //Here we set the library format, which specifies how the output bundle should be exposed library: { type: 'module', }, path: path.resolve('build', 'static'), }, plugins: [ new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1, }), ], };Note that we’ve added the
libraryformat, which specifies how the output bundle should be exposed. - 
	
Save the file.
 - 
	
From the
clarity-ticketing-ui/publicfolder, open theindex.htmlfile in a text editor or IDE. - 
	
Replace the
<tickets-root>tag with a<clarity-ticketing-ui>tag, the name of our custom element.
Your final result should resemble this:<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Clarity Ticketing UI</title> </head> <body> <clarity-ticketing-ui></clarity-ticketing-ui> <script type="module" src="build/static/index.js"></script> </body> </html> - 
	
Save the file.
 - 
	
Paste the following code into the
clarity-ticketing-ui/index.jsfile.import React, { useState, useEffect } from 'react'; import ReactDOM, { render } from 'react-dom'; import './assets/style.css'; import TicketsList from './assets/components/TicketsList'; import { HashRouter, Route, Routes } from "react-router-dom"; import App from './App'; // Custom Element class class CustomElement extends HTMLElement { connectedCallback() { // Ensure the React component is rendered only once if (!this.rendered) { // Create a container if it doesn't exist const container = document.createElement('div'); container.id = 'tickets-root'; this.appendChild(container); // Render the React component into the container ReactDOM.render(<TicketsList />, container); this.rendered = true; } } disconnectedCallback() { // Clean up the React component when the element is removed const container = this.querySelector('#tickets-root'); if (container) { ReactDOM.unmountComponentAtNode(container); } this.rendered = false; } } // Define the custom element const ELEMENT_NAME = 'clarity-ticketing-ui'; if (!customElements.get(ELEMENT_NAME)) { customElements.define(ELEMENT_NAME, CustomElement); } // Automatically add the custom element to the page if not already present document.addEventListener('DOMContentLoaded', () => { if (!document.querySelector(ELEMENT_NAME)) { const customElement = document.createElement(ELEMENT_NAME); document.body.appendChild(customElement); } });This replaces the default use of
render()on theticket-rootdiv, leveraging a Web Component to define the React app as a reusable and self-contained custom element. - 
	
Save the file.
 - 
	
Create a new file named
client-extension.yamlin theclarity-ticketing-ui/folder and add the following code.assemble: - from: build/static into: static clarity-ticketing-ui: friendlyURLMapping: clarity-ticketing-ui htmlElementName: clarity-ticketing-ui instanceable: false name: Clarity Ticketing UI portletCategoryName: category.client-extensions type: customElement urls: - index.*.js useESM: true - 
	
Move the
clarity-ticketing-ui/folder into theclient-extensions/folder of your course workspace. - 
	
Open a terminal and navigate to the
client-extensions/clarity-ticketing-ui/folder. - 
	
Run this command to build and deploy the custom element client extension:
blade gw clean deploy - 
	
Verify that the client extension deploys successfully:
2025-01-28 11:50:59.076 INFO [fileinstall-directory-watcher][BundleStartStopLogger:68] STARTED clarityticketingui_7.4.13 [1462]Now that you've deployed the custom element client extension, examine the ticketing app UI.
 - 
	
In your Liferay instance, sign in as the Clarity Admin user.
- Username: 
admin@clarityvisionsolutions.com - Password: 
learn 
 - Username: 
 - 
	
Open the Site Menu (
), click Page Tree, and select the Tickets page.
 - 
	
Click Edit (
) to start editing the page.
 - 
	
In the Fragments and Widgets search bar, search for
Clarity Ticketing UI. - 
	
Drag and drop the Clarity Ticketing UI widget to the page.
 - 
	
Click Publish.
 
You've now learned how to deploy custom element client extensions, giving you more control over your application.
Conclusion
Great! You’ve successfully deployed a custom element client extension for retrieving and displaying Clarity’s ticket data. Next, you’ll learn about a different use case for custom elements as remote applications.
Capabilities
Product
Education
Knowledge Base
Contact Us