Control Hooks

Client-side configuration for bringing custom field controls to the visual editor.

Custom fields in the visual editor are stored as individual HTML files. When the visual editor loads one of these files, it injects a control.js file, which opens a communication channel between the field and the visual editing API.

Undefined Object Guards

Because the window.stackbit object is injected by the visual editor, it might be not available when the HTML file is first loaded. To ensure that the object is available, custom fields should wait for the DOM to load or manually instantiate the global object.

  • 1
  • 2
  • 3
  • 4
<script>
  // Safely initialize the stackbit object
  window.stackbit = window.stackbit || {}
</script>

When custom control environment is initialized, the event stackbitInitialized is emitted.

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
<script>
  const handler = () => {
    window.stackbit.runAction();
  };

  if (window.stackbit) {
    handler();
  } else {
    window.addEventListener('stackbitInitialized', handler);
  }
</script>

window.stackbit Properties

The properties documented below are available on the window.stackbit object, which is injected into the HTML file by the visual editor.

See the custom fields guide for example usage and common scenarios.

onUpdate

This property's value is a callback function definition. The visual editor calls this function when the field is displayed, and when its value is updated.

The function receives a single options parameter, which is an object with the following properties:

Usage Example

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
<script>
  // Safely initialize the stackbit object
  window.stackbit = window.stackbit || {}

  window.stackbit.onUpdate = (options) => {
    // Use the init option to attach event listeners to elements within the custom
    // field.
    if (options.init) {
      // Set up the custom field: attach event listeners for interactivity, set
      // desired size of the control, etc...
    }
  }
</script>

Callback Options

init
(boolean) When true, the function is running for the first time. This is typically used as a signal to add event handlers to the DOM.
updateDocument
(object) Object with properties and functions used for updating the document, usually based on interaction with the DOM of the HTML file. This matches the updateDocument object used in the onDocumentUpdate hook, which calls updateDocument on the applicable content source.
document
(Document) The root document, without its context.
model
(Model) The model for the current document.
fieldPath

(array, containing strings or numbers) The path to the field within the document object, using dot notation for nested content.

This is typically used to access and update the field's value within documents with nested content.

documentField
(object) Field object within the document. This is also available on document and can be discovered using fieldPath.
modelField
(object) Field definition for the field being updated on the document's model.
setDesiredControlSize

(function) Function that configures the field to an optimal size. The function accepts a single options parameter, with width and height properties (in pixels, as numbers).

Note that the size won't always be as specified, as it is contingent on the space available for the field or modal.

close
(function) Used to close the modal. This is only available when using the custom-modal-html control type.
navigate

(function) Navigate to a different fieldPath or document. The function accepts a single options parameter, which can contain a single fieldPath property if accessing a field path on the current document.

If moving to another document, the following properties should be used:

  • srcType
  • srcProjectId
  • srcDocumentId
  • fieldPath (optional)
currentLocale
(string, optional) The current locale of the editor.
currentPageUrl
(string, optional) The currently viewed page in the the visual editing UI, if available.

options

This property's value is a last received options argument from onUpdate method.

runAction

Run a custom action within the visual editor.

By providing only one required property actionName, visual editor will search for the action with that name within the current field. If you provide additional specifiers for the a different field, visual editor will search for the action in that field.

Returns a Promise, which resolves or rejects once the custom action finishes its execution. The value of promise is one of:

  • customAction.result
  • customAction.success
  • customAction.error

If the custom action requires user input, and it wasn't provided when calling the method, a Promise is still returned but also a user facing form will appear.

Usage Example

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
<script>
  // run action with name action for current field
  window.stackbit?.runAction({
    actionName: 'action'
  }).then((result) => {
    // handle success
  }).catch((err) => {
    // process error
  });

  // run action for the same document but different field
  window.stackbit?.runAction({
    actionName: 'action',
    fieldPath: ['title']
  });

  // run action for the different document
  window.stackbit?.runAction({
    actionName: 'action',
    srcDocumentId: 'other-document-id',
    fieldPath: ['title']
  });

  // run action for the different document in other content store
  window.stackbit?.runAction({
    actionName: 'action',
    srcType: 'git',
    srcProjectId: 'other-project',
    srcDocumentId: 'other-document-id',
    fieldPath: ['title']
  });

  // run global action with input data
  window.stackbit?.runAction({
    actionName: 'action',
    actionType: 'global',
    inputData: {
      message: 'Hello'
    }
  });

  // run bulk action
  window.stackbit?.runAction({
    actionName: 'action',
    actionType: 'bulk',
    actionTarget: {
      objects: [
        { srcType: 'git', srcProjectId: 'project', srcDocumentId: 'doc-1' },
        { srcType: 'git', srcProjectId: 'project', srcDocumentId: 'doc-2' }
      ]
    }
  });
</script>

Options

actionName
(string) The name of the action to run. By default, Netlify searches for the action within the custom actions defined for this field. To execute an action from a different field in the same or another document, specify additional properties such as fieldPath, srcDocumentId, srcType, and srcProjectId. To execute global or bulk actions specify actionType.
fieldPath
(array, containing strings or numbers, optional) The field path specifies the location of the field containing the action to run. By default, the current field's path is used. If srcDocumentId is specified, fieldPath should indicate the location of the field in that document.
srcType
(string, optional) Specifies the content source containing the action to run. By default, the current content source type is used.
srcProjectId
(string, optional) Specifies the content source project ID containing the action to run.
srcDocumentId
(string, optional) Specifies the document containing the action to run. By default, the current document's ID is used.
locale
(string, optional) The document or field locale for which to run the action. Actions executed in the context of localized documents or fields are scoped to a specific locale. For example, an editor may execute the same 'translate' action for a field in two different locales simultaneously.
inputData
(object, optional) The input data for the action. If the action has required fields in its inputData but the inputData option is not provided, the visual editor will present a modal to collect the input data from the user.
actionType
(string, optional) Set actionType to global or bulk to run global or bulk actions, respectively. If actionType is set to bulk, you must also specify actionTarget.objects.
actionTarget
(object, optional) When actionType is 'bulk', actionTarget specifies the target documents the action runs for.