Creating custom URL dialogs

A URL dialog is a special TinyMCE UI component which loads an external web page inside a dialog (sometimes referred to as modals). URL dialogs are useful for very complex use cases, where the supported components for TinyMCE’s standard dialogs cannot be used. For example, a custom file manager that is loaded inside a TinyMCE dialog would probably require a URL dialog.

Standard TinyMCE dialogs should suffice for most use cases, and may be simpler to configure.

Basic example

The configuration for a basic URL dialog might look like this:

  title: 'Just a title',
  url: ''

URL dialog configuration

A URL Dialog configuration has three main parts to match the three main parts of the dialog’s UI:

  • Title: The title of the dialog. This will display in the header of the dialog.

  • URL: The URL of the external page to load inside the dialog.

  • Buttons: (Optional) An array of footer buttons that are displayed in the dialog’s footer.


Name Value Requirement Description




The title of the dialog.




The URL to the external page to load.




The width of the dialog in pixels.




The height of the dialog in pixels.




An array of buttons to render in the footer of the dialog.


(dialogApi, details) => void


Function invoked when a Custom type footer button is clicked.


(dialogApi) => void


Function invoked when the dialog is cancelled. The dialog header’s close button and a Cancel type footer button invoke this function.


() => void


Function invoked when the dialog is closed. The dialog header’s close button, a Cancel type footer button and the dialog instance API’s close() method invoke this function.


(dialogApi, details) => void


Function invoked when a message is received from the external page.

For more information on the dialogApi object that is passed to some of the configuration options, see the URL dialog instance API documentation.

A button is a clickable component that can contain text or an icon. There are two types of buttons (primary and secondary buttons), though the only difference is that they are styled differently. Primary buttons are intended to stand out. The color will depend on the chosen skin.


Name Type Requirement Description


'cancel' or 'custom'


Must be 'cancel' or 'custom' based on the type of callback function that should be invoked when the button is clicked.




Text to display in the button if icon is not specified. Also used for the button’s title attribute.




An identifier for the button. If not specified, the button will be assigned a randomly generated name.




Name of the icon to be displayed. Must correspond to an icon: in the icon pack, in a custom icon pack, or added using the addIcon API. When configured, the button will display the icon instead of text.


'primary', or 'secondary'


default: 'secondary' - Whether to style the button as a primary, or secondary button.




default: true - When false, the button will be disabled when the dialog loads.


'end' or 'start'


default: 'end' - When set to 'end' the button will display on the right-hand side of the dialog. When set to 'start' the button will display on the left-hand side.

Buttons do not support mixing icons and text at the moment.

Button types and event callbacks

The different footer button types will invoke different callbacks when clicked:

  • A Cancel type button will invoke the onCancel and onClose callback functions provided in the dialog configuration. These callback functions are also fired when a user clicks the X button in the top right of the dialog.

  • A Custom type button will invoke the onAction callback function provided in the dialog configuration, and pass it the button’s name in the details object. This allows developers to create a click handler for each Custom type footer button in the dialog. See the Redial example for an example of how to use this with standard dialogs.

Unlike standard dialogs, URL dialogs do not have a Submit type footer button, and therefore do not have an onSubmit callback.

See the URL dialog configuration options documentation for more information on event callbacks.

URL dialog instance API

When a URL dialog is created, a dialog instance API is returned. For example, const instanceApi = editor.windowManager.openUrl(config);. The URL dialog API instance is also passed to some of the dialog configuration options.

The instance API is a JavaScript object containing methods attached to the dialog instance. When the dialog is closed, the instance API is destroyed.

Instance API methods

Methods Description

block(message: string) => void

Calling block() and passing a message string will disable the entire dialog window and show a loading image. This is useful for handling asynchronous data. The message is used for screen reader accessibility. When the data is ready use unblock() to unlock the dialog.

unblock() => void

Calling unblock() will unlock the dialog instance restoring functionality.

close() => void

Calling the close() method will close the dialog. When closing the dialog, all DOM elements and dialog data are destroyed. When open(config) is called again, all DOM elements and data are recreated from the config.

sendMessage(data) => void

Calling the sendMessage() method will attempt to send a message to the external page via window.postMesssage().

URL dialog messaging

When using a URL dialog, there needs to be a way to communicate between TinyMCE and the external page, as the two components are no longer running in the same window. To allow this, TinyMCE makes use of the browsers window.postMessage() API to allow sending data across different origins. The following is an example of how to send messages back to TinyMCE from within an external page:

  mceAction: 'insertContent',
  content: 'Some content'
}, '*');

Similarly, to send messages from TinyMCE back to the external page, the sendMessage() function from the URL dialog instance API can be used to send messages, and then in the external page an event listener can be added to receive the messages:

window.addEventListener('message', (event) => {
  var data =;

  // Do something with the data received here
  console.log('message received from TinyMCE', data);
When sending a message it is recommended to specify the target origin of where TinyMCE is running, instead of using a wildcard ('*'). Similarly, when receiving messages, check that event.origin matches the origin of where TinyMCE is running. For example, if TinyMCE is running on, then if event.origin doesn’t match the message should be ignored.

Supported message actions

These actions are built into the URL dialog functionality and will perform an action inside the editor based on the mceAction specified. The actions supported are:


This action inserts content into the editor at the current selection. The content property specifies what content should be inserted into the editor.

 mceAction: 'setContent',
 content: 'My custom content'


This action is used to set the editors content. The content property specifies what content should be set inside the editor.

  mceAction: 'setContent',
  content: 'My custom content'


This action executes a command inside the editor. The options available for this action are:

  • cmd: The name of the command to be executed inside the editor.

  • ui: An optional boolean to specify if a UI (dialog) should be presented or not.

  • value: An optional value to be used by the command.

  mceAction: 'execCommand',
  cmd: 'mceInsertLink',
  value: ''


This action closes the open URL dialog. This is the same as using the api.close() function.

  mceAction: 'close'


This action disables the entire dialog window and shows a loading image. This is the same as using the api.block(message) function.

  mceAction: 'block',
  message: 'Loading…'


This action unblocks the window/dialog. This is the same as using the api.unblock() function.

  mceAction: 'unblock'

Custom message actions

A custom message is one that contains a mceAction not listed in the above-supported actions. For example, the following snippet could be used to send a message back to TinyMCE and then be processed via the onMessage callback to perform custom actions inside TinyMCE.

  mceAction: 'customAction',
  data: {
    customField: 'custom value'
TinyMCE will ignore all messages received that don’t contain a mceAction property.

Interactive example

This example shows a toolbar button that opens an external URL inside a 640px by 640px dialog without any footer buttons. The dialog can be opened by clicking the {;} toolbar button.

  • TinyMCE

  • HTML

  • JS

<textarea id="url-dialog">
  <p>Click on the custom {;} toolbar button.</p>
  selector: 'textarea#url-dialog',
  toolbar: 'urldialog',
  height: 300,
  setup: (editor) => {
    editor.ui.registry.addButton('urldialog', {
      icon: 'code-sample',
      onAction: () => editor.windowManager.openUrl({
        title: 'URL Dialog Demo',
        url: 'external-page.html',
        height: 640,
        width: 640
  content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:16px }'