Develop a Document Field Integration

Introduction

Goal

Develop a document field integration using the UI Extension client library.

Background

A document field integration 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. Content type developers provide the field caption and hint. The field is configured as a custom integration and is shown in an iframe and provides the UI to set the String value.

The content editor and document field communicate using the 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 field. 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 field integration to interpret the string, e.g. parse it as JSON.

Without any parameters, the value of the 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('brxsaas:title');
  • ui.document.field.getValue('brxsaas:mymultiple', 1);
  • ui.document.field.getValue('brxsaas:mycompound', 'brxsaas:name');
  • ui.document.field.getValue('brxsaas:mymultiplecompound', 1, 'brxsaas:name');

👍

When accessing other field values in the same compound field, you may use "." to specify the name of the current compound field where both the other field and your document field integration field belong. You can also skip the compound field index for convenience like in the following examples:

Equivalent to ui.document.field.getValue('brxsaas:mycompound', 'brxsaas:name'); if the current compound field name is brxsaas:mycompound:
ui.document.field.getValue('.', 'brxsaas:name');

Equivalent to ui.document.field.getValue('brxsaas:mymultiplecompound', 1, 'brxsaas:name'); if current compound field name is brxsaas:mymultiplecompound and it is located at the second. The zero-based index is automatically detected for convenience.
ui.document.field.getValue('.', 'brxsaas:name');

Note: Whether the compound field is multiple or not, the API call is 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 document field integration module cannot easily determine the compound field's name and index 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 up to 100K characters to avoid storing unreasonable amounts of data (e.g. when an integration 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 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 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.

👍

In the same way as ui.document.field.getValue() APIs are shown above, you may use "." to specify the name of the current compound field where both the other field and your document field integration field belong. You can also skip the compound field index for convenience, too.

ui.document.field.setHeight()
Sets the height of the iframe that surrounds the document field integration 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 integration configuration.

ui.document.open()
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()
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/brxsaas/content/sample-document"

Code Example

👍

For simplicity, this is a plain HTML/JavaScript example. Document field integrations can be developed using your JS framework and tools of choice, such as Angular, Vue, React, etc.

This "Hello World" example of a document field integration renders a button and sets the field value to "Hello Button" when the user clicks the button.

The HTML for the integration renders the button and loads the client library and the script for the integration:

<!doctype html>
<html>
  <head>
    <title>Document Field Integration 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:

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;
}

Did this page help you?