liferay-globaljs-editor-extension

Builds globalJS Client Extensions that customize Liferay Data Engine field editors client-side.

Updated Jul 24, 2026
One-click install
npx skills add https://github.com/gweone/agent-plugins --skill liferay-globaljs-editor-extension-gweone
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: liferay-globaljs-editor-extension
Source: https://github.com/gweone/agent-plugins/tree/main/plugin/sharpps-liferay/skills/liferay-globaljs-editor-extension
Command: npx skills add https://github.com/gweone/agent-plugins --skill liferay-globaljs-editor-extension-gweone

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Liferay's Data Engine renders form fields (Document Types, Objects, Forms) with unpredictable IDs, async mounting, and non-native controls, making it hard to add client-side behavior like conditional show/hide, live hints, or submit blocking without replacing the editor or writing an OSGi module. ## Core Features & Use Cases - Screen and field targeting: Detect the correct portlet screen via render-request query params, resolve Document Type IDs by externalReferenceCode, and locate rendered fields using tag-restricted ddm$$<fieldName>$ selectors or stable data-qa-id containers. - Robust async behavior: Wait for asynchronously rendered fields with scoped MutationObservers, debounce mutation callbacks, guard against re-entrancy, and parse JSON-encoded values from hidden inputs behind custom comboboxes. - Client-side submit blocking: Intercept form submission with a capture-phase submit listener to block Publish/Save on a condition, without monkey-patching Liferay internals. - Use Case: Add a live format hint to a Document Type field, show or hide one field based on another field's selection, and block the Publish button when a validation condition fails — all from a single type: globalJS Client Extension. ## Quick Start Build a globalJS Client Extension that hides the Category field on a Document Type edit screen unless the Type field is set to a specific value.

Frequently Asked Questions about liferay-globaljs-editor-extension

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I customize a Liferay Data Engine field editor with a Client Extension?

Use a single type: globalJS Client Extension with company scope and an internal registry that dispatches to purpose-specific extensions. Detect the target screen via p_p_id and mvcRenderCommandName query params, then attach behavior to fields found with tag-restricted ddm$$ selectors.

Why can't I find a Liferay form field with querySelector?

Data Engine renders fields asynchronously, so the field may not exist in the DOM when your code runs. Wait for it with a MutationObserver scoped to a narrow ancestor, and use the stable ddm$$<fieldName>$ substring restricted to input, select, and textarea tags.

How do I read the value of a Liferay select field in JavaScript?

A non-multiple select renders as a custom combobox backed by a hidden input whose value is a JSON-encoded array string like ["report"]. Parse it with JSON.parse rather than comparing the raw value, and re-read it on DOM mutations since change events do not reliably fire.

Can a globalJS Client Extension block the Publish button in Liferay?

Yes, purely client-side, by adding a capture-phase submit listener on document that calls preventDefault and stopImmediatePropagation when your condition fails. This only blocks the UI's own submit; enforcement for all clients requires backend validation.

What are the limitations of a globalJS Client Extension for DDM fields?

No Client Extension type hooks into the DDM field-type registry, DDMValidation, or DDMExpressionFunction. Everything is DOM manipulation layered on Liferay's rendering; replacing an editor component or adding a reusable validator requires a traditional OSGi module.