Custom element rendering for properties rail by data-type
This feature allows third-party developer to build custom input UI for specific data types in the Universal Editor. The custom UI is rendered in an iframe and replaces the standard UI for the field in the properties rail.
Define data types
An UIX extension can be used to introduce new data types or replace the standard data type renderer shipped with the Universal Editor. The newly created data type will be rendered in an iframe using the custom UI provided by the extension.
Check this document to learn about available data types for Universal Editor.
function ExtensionRegistration() {
const init = async () => {
const guestConnection = await register({
id: extensionId,
methods: {
canvas: {
getRenderers() {
return [
{
dataType: "text",
url: '/#/renderer/1'
},
{
dataType: "custom-type",
url: '/#/renderer/2',
},
];
},
},
},
});
};
init().catch(console.error);
return <Text>IFrame for integration with Host (AEM)...</Text>;
}
Implement custom rendering logic
- Define the router in the extension application to handle the custom rendering of the field.
function App() {
return (
<Router>
<ErrorBoundary onError={onError} FallbackComponent={fallbackComponent}>
<Routes>
<Route index element={<ExtensionRegistration />} />
<Route
exact
path="index.html"
element={<ExtensionRegistration />}
/>
<Route
exact path="renderer/:rendererId"
element={<TypeRenderer />}
/>
</Routes>
</ErrorBoundary>
</Router>
)
// Methods
// error handler on UI rendering failure
function onError(e, componentStack) {}
// component to show if UI fails rendering
function fallbackComponent({ componentStack, error }) {
...
}
export default App
- Implement custom data type
export default () => {
const [isLoading, setIsLoading] = useState(true);
const [connection, setConnection] = useState();
const [model, setModel] = useState();
const [value, setValue] = useState();
const [error, setError] = useState();
const [validationState, setValidationState] = useState();
const { rendererId } = useParams();
if (!rendererId) {
console.error('Renderer id parameter is missed');
return;
}
useEffect(() => {
const init = async () => {
// connect to the host
const connection = await attach({ id: extensionId });
setConnection(connection);
// get model
setModel(await connection.host.field.getModel());
// get field value
setValue(await connection.host.field.getValue());
// get field error
setError(await connection.host.field.getError());
// get field validation state
setValidationState(await connection.host.field.getValidationState());
setIsLoading(false);
};
init().catch((e) =>
console.log("Extension got the error during initialization:", e)
);
}, []);
const onChangeHandler = (v) => {
console.log("onChange on extension side", v);
connection.host.field.onChange(v);
};
return (
<Provider theme={lightTheme} colorScheme="light">
{!isLoading ? (
<>
Content generated by the extension Renderer#{rendererId}
<Flex direction="column" gap="size-65" marginBottom="size-100">
<TextField
validationState={error ? "invalid" : validationState}
label={model.multi ? null : model.label}
aria-label={model.label || model.name}
defaultValue={value}
maxLength={model.validation.maxLength}
isReadOnly={model.readOnly}
isDisabled={model.readOnly}
isRequired={model.required}
errorMessage={error}
onChange={onChangeHandler}
width="100%"
/>
</Flex>
</>
) : (
<View width="97%" height="100%">
<Spinner />
</View>
)}
</Provider>
);
};
Extension Registration Reference
Field
Type
Required
Description
url
string✔️
URL of the page to load in the iframe that will replace the original field. The URL must have the same origin as the extension declaring the rules for field replacement.
dataType
string✔️
Value of
component in the model definitionicon
stringIcons to be displayed in the properties rail if data type is matched.
Field Reference
{
await connection.host.field
}
Methods
Description
getModelReturns the model of the field.
getValueReturns the value of the field.
getErrorReturns the error of the field.
getValidationStateReturns the validation state of the field.
onChangeSets the value of the field.
setHeightSets the height of the field.