Home/Field Guide/Practice & reference
LAB 03
Ship a custom-element widget
Package a vanilla JavaScript custom element and verify it in the page editor.
Before you begin
Use a target-aligned Liferay Workspace and an instance with Custom Element client extension support. This example renders illustrative data and requires no npm install or credentials. Create client-extensions/partner-status-card/ with the following files.
1. Declare the extension
assemble:
- from: assets
into: static
partner-status-card:
htmlElementName: partner-status-card
instanceable: true
name: Partner Status Card
portletCategoryName: category.client-extensions
type: customElement
urls:
- index.js
useESM: false
Save this as client-extension.yaml. The asset path is relative to the assembled static directory.
2. Register the element
Save this as assets/index.js.
(() => {
const tag = "partner-status-card";
if (customElements.get(tag)) {
return;
}
class PartnerStatusCard extends HTMLElement {
connectedCallback() {
const label = document.createElement("strong");
label.textContent = "Partner request status";
const status = document.createElement("p");
status.textContent = "Example request · Awaiting review";
this.replaceChildren(label, status);
}
}
customElements.define(tag, PartnerStatusCard);
})();
3. Package, place, and verify
Run the following from Workspace, using gradlew.bat on Windows. Adjust the Gradle path to match projects.
./gradlew projects
./gradlew :client-extensions:partner-status-card:clean :client-extensions:partner-status-card:deploy
Use local deploy only for a Workspace configured for it. For other environments, use the documented packaging and deployment route. Confirm registration, edit a disposable content page, and add Partner Status Card from the widgets. Publish the page and add a second copy to test multiple instances.
Open the browser console and evaluate customElements.get("partner-status-card"). It should resolve to the class. If no widget is listed, verify extension registration and permissions. If the widget is listed but blank, confirm the asset loads and the JavaScript tag matches the YAML.
