Develop a Document Field Extension
Introduction
Goal
Develop a document field extension using the Open UI extension library.
Background
A Document Field Extension functions as a field in a document type. It appears in a document editing template just as any other field and can be used to set a String property in the document. The Bloomreach Experience Manager content editors provide the field caption and hint. The extension is shown in an iframe and provides the UI to set the String value.
The communication between the Bloomreach Experience Manager editor and the extension is done using the Open UI Extension client library.
API
Functions
- ui.document.get()
Returns a promise that resolves with information about the current document. The resolved object has the following properties:
Property Description Example value id The UUID of the document handle node. displayName The display name of the document. "My Document" locale The locale of the document. "en" mode The mode of the editor that shows the extension. Either "view", "edit" or "compare". "view" urlName The URL name of the document. "my-document" variant.id The UUID of the document variant node. - ui.document.field.getValue()
Returns a promise that resolves with the current string value of a field. It's up to the extension to interpret the string, e.g. parse it as JSON.
Without any parameters, the value of the OpenUI field itself is returned.
Optionally, a 'path' string array parameter can be passed, pointing to a field or a nested subfield within the current document. For multiple-valued fields, use zero-based indices to access specific values.
Examples:- ui.document.field.getValue();
- ui.document.field.getValue('myproject:title');
- ui.document.field.getValue('myproject:mymultiple', 1);
- ui.document.field.getValue('myproject:mycompound', 'myproject:name');
- ui.document.field.getValue('myproject:mymultiplecompound', 1, 'myproject:name');
- // equivalent to `ui.document.field.getValue('myproject:mycompound', 'myproject:name');`
// if the current compound field name is 'myproject:mycompound'.
ui.document.field.getValue('.', 'myproject:name'); - // equivalent to `ui.document.field.getValue('myproject:mymultiplecompound', 1, 'myproject:name');`
// if current compound field name is 'myproject:mymultiplecompound' and it is located at the second.
// the zero-based index is automatically detected for convenience.
ui.document.field.getValue('.', 'myproject:name');
Note: Since v14.7, whether the compound field is multiple or not, the API call is exactly the same because the internal backend API resolves the details of the current compound field automatically. This helps avoid the complexity in implementation especially when the OpenUI Document Field Extension module cannot determine easily the name and the index of the compound field where it belongs.
- ui.document.field.setValue()
Updates the string value of the field. Returns a promise that resolves when the value has been set. The string can contain at most 100K characters to avoid the storage of unreasonable amounts of data (e.g. when an extension gets compromised). Larger strings will be ignored and return a rejected promise.
Note that validation of the set value is not reflected in the returned promise. A resolved promise just means the value reached the surrounding editor. Any client-side validation (e.g. the 'required' check) may still trigger the field to become invalid.
- ui.document.field.getComparedValue()
Only available when the "mode" of the document is "compare". Returns a promise that resolves with the string value of a field value to compare.
Without any parameters, the value of the OpenUI field itself is returned.
Optionally, a 'path' string array parameter can be passed, pointing to a field or a nested subfield within the current document. For multiple-valued fields, use zero-based indices to access specific values.Since v14.7, in the same way as ui.document.field.getValue() APIs shown above, you may use "." to specify the name of the current compound field where both the other field and your OpenUI Document Field Extension field belong, and you can skip the compound field index for convenience, too. - ui.document.field.setHeight()
Sets the height of the iframe that surrounds the document field extension to the given number of pixels. Valid values are from 10 to 2000. When calling the function with the value 'auto', the iframe is set to the height of the iframe. This gives the option to show the iframe without scrollbars. When the size of the iframe content changes, the height of the iframe is automatically adjusted. When calling the function with the value 'initial', the iframe is set to the initial height from the extension configuration.
- ui.document.open()
Available since v14.2.1
Opens a document by UUID in the content perspective.
Returns a Promise that resolves when the document is opened.
Property Description Example value id The UUID of the document handle node. "c580ac64-3874-4717-a6d9-e5ad72080abe"
- ui.document.navigate()
Available since v14.2.1
Navigates a document path in the content perspective.
Returns a Promise that resolves when the document is opened.
Property Description Example value path The absolute JCR path of the document handle node. "/content/documents/myproject/content/sample-document"
Dialog
A Document Field Extension can open a dialog to interact with the user.
Code Example
This "Hello World" example of a document field extension renders a button and sets the field value to "Hello Button" when the user clicks the button.
The HTML for the extension renders the button and loads the client library and the script for the extension:
index.html
<!doctype html> <html> <head> <title>Document Field Extension Example</title> <script type="text/javascript" src="https://unpkg.com/@bloomreach/[email protected]/dist/ui-extension.min.js"></script> <script type="text/javascript" src="index.js"></script> </head> <body> <p>Value: <span id="fieldValue"></span></p> <button id="setFieldValue">Set Field Value</button> </body> </html>
The script registers the extension, shows the field value, enables the button, and adds an event listener to the button to set the field value when the user clicks the button:
index.js
document.addEventListener('DOMContentLoaded', async () => { try { const ui = await UiExtension.register(); const brDocument = await ui.document.get(); const value = await ui.document.field.getValue(); showFieldValue(value); initSetFieldValueButton(ui, brDocument.mode); } catch (error) { console.error('Failed to register extension:', error.message); console.error('- error code:', error.code); } }); function initSetFieldValueButton(ui, mode) { const buttonElement = document.querySelector('#setFieldValue'); if (mode !== 'edit') { buttonElement.style.display = 'none'; return; } buttonElement.style.display = 'block'; buttonElement.addEventListener('click', async () => { try { var value = 'Hello Button'; ui.document.field.setValue(value); showFieldValue(value); } catch (error) { console.error('Error: ', error.code, error.message); } }); } function showFieldValue(value) { document.querySelector('#fieldValue').innerHTML = value; }