Configuring custom dialogs
A dialog configuration has three main parts to match the three main parts of a dialog’s UI.
-
Title
-
the dialog’s title.
-
It displays in the dialog’s header.
-
-
Body
-
the dialog’s body.
-
The body component can be a panel or a tab panel, which can contain an array of panel components such as buttons, inputs and text.
-
-
Buttons
-
An array of footer buttons that are displayed in the dialog’s footer.
-
Basic example
The configuration for a basic dialog that displays HTML information might look like this:
tinymce.activeEditor.windowManager.open({
title: 'Dialog Title', // The dialog's title - displayed in the dialog header
body: {
type: 'panel', // The root body type - a Panel or TabPanel
items: [ // A list of panel components
{
type: 'htmlpanel', // an HTML panel component
html: 'Panel content goes here.'
}
]
},
buttons: [ // A list of footer buttons
{
type: 'submit',
text: 'OK'
}
]
});
Options
Name | Value | Requirement | Description |
---|---|---|---|
title |
string |
required |
The title of the dialog. This will display in the header of the dialog. |
body |
|
required |
The specification for the body component. |
buttons |
|
required |
An array of footer buttons to render in the footer of the dialog. |
size |
|
optional |
default: |
initialData |
object |
optional |
An object containing initial values for the dialog’s panel components. |
onAction |
|
optional |
Function invoked when a user interacts with a |
onSubmit |
|
optional |
Function invoked when a Submit type footer button is clicked. |
onCancel |
|
optional |
Function invoked when the dialog is cancelled. The dialog header’s close button and a Cancel type footer button invoke this function. |
onChange |
|
optional |
Function invoked when the value of an |
onClose |
|
optional |
Function invoked when the dialog is closed. The dialog header’s close button, a Cancel type footer button and the dialog instance API’s |
onTabChange |
|
optional |
This method only applies to tab panel dialogs. Function invoked when the user changes tabs. |
For more information on the dialogApi
object that is passed to some of the configuration options, see the dialog instance API documentation.
Event callback functions
Each of the event callback functions - onAction
, onSubmit
, onCancel
, onChange
, onClose
, and onTabChange
- are shared between all dialog components that may trigger them. For example, Custom type footer buttons and dialog panel buttons all trigger onAction
. Therefore, callback functions that may be triggered by multiple components are passed an object (called details
above) that contains the name
of the component that triggered the event.
Any callback function that is not passed a details
object assumes that the dialog will only contain one component which can trigger it or that it does not matter if the function is triggered by multiple components. For example, onSubmit
is only triggered when a user clicks on a Submit type footer button, and TinyMCE assumes that a dialog will only have one Submit type button. In comparison, onCancel
and onClose
are both triggered by clicking the X
button in the top right of a dialog or by clicking a Cancel type footer button. These two buttons have the same functionality, and therefore TinyMCE does not differentiate between them.
Configuration parameters
align
This feature is only available for TinyMCE 6.6 and later. |
align
is an optional property to add to dialog labels to set the alignment of the label text.
The property has a default value of start
.
This is also the value applied if the property is not explicitly set.
Type: String
Possible values: '+start+'
, '+center+'
, end
Default value: start
The values, start
and end
, refer to the beginning or end of a text line and are relative to the display language.
For left-to-right written languages (eg English or Vietnamese), start
sets the dialog label as left-aligned and end
sets the dialog label as right-aligned.
For right-to-left written languages (eg Arabic or Persian), start
sets the dialog label as right-aligned and end
sets the dialog label as left-aligned.
Example: using align
to set a dialog caption as end-aligned
tinymce.activeEditor.windowManager.open({
title: 'Dialog Title', // The dialog's title - displayed in the dialog header
body: {
type: 'panel', // The root body type - a Panel or TabPanel
items: [
{
type: 'label', // component type
label: 'Caption', // text for the group label
align: 'end',
items: [
{
type: 'htmlpanel', // an HTML panel component
html: 'Panel content goes here.'
}
]
}
]
},
buttons: [ // A list of footer buttons
{
type: 'submit',
text: 'OK'
}
]
});
border
This feature is only available for TinyMCE 6.6 and later. |
border
is an optional property, available to add to the iframe
dialog component.
The property has a default value of false
.
When this property is set to true
, a border displays around the iframe
component.
The border is also highlighted when the iframe
component takes focus (by, for example, using the Tab key to change focus within the active dialog).
Type: Boolean
Possible values: true
, false
Default value: false
Example: using border
to display a border around an iframe
component
tinymce.activeEditor.windowManager.open({
title: 'Dialog Title', // The dialog's title - displayed in the dialog header
body: {
type: 'panel', // The root body type - a Panel or TabPanel
items: [ // A list of panel components
{
name: 'preview',
type: 'iframe',
border: true,
}
]
},
buttons: [ // A list of footer buttons
{
type: 'submit',
text: 'OK'
}
]
});
Using buttons
to configure a dialog without a footer
This feature is only available for TinyMCE 6.6 and later. |
In addition to its usual functions, the buttons
property can also be used to stop the footer section from displaying.
To configure a custom dialog so it does not render a footer section when displayed, set the buttons
property to an empty array, []
, or omit it entirely.
basic example of a dialog without buttons or a footer
tinymce.activeEditor.windowManager.open({
title: 'Dialog Title', // The dialog's title - displayed in the dialog header
body: {
type: 'panel', // The root body type - a Panel or TabPanel
items: [ // A list of panel components
{
type: 'htmlpanel', // an HTML panel component
html: 'Panel content goes here.'
}
]
},
buttons: []
});
persistent
This feature is only available for TinyMCE 6.6 and later. |
The persistent
property, when set to true
, allows an inline dialog to stay open when the dialog no longer has focus.
If an end-user gives another part of the TinyMCE editor focus (for example, the document editor, or a menu), the inline dialog will stay open.
Setting the property to true
does not over-ride normal mechanisms for closing a dialog, such as clicking the Close button or pressing the Esc key.
The property has a default value of false
.
If an inline dialog is open and focus is switched away from the TinyMCE editor entirely (by, for example, the end-user switching focus to an available host-browser UI element), an open inline dialog will remain open regardless of the persistent property’s value. This was the behavior prior to this property being available and continues to be the behavior.
|
Type: Boolean
Possible values: true
, false
Default value: false
Example: using persistent
tinymce.activeEditor.windowManager.open({
title: 'Dialog Title', // The dialog's title - displayed in the dialog header
body: {
type: 'panel', // The root body type - a Panel or TabPanel
items: [ // A list of panel components
{
type: 'htmlpanel', // an HTML panel component
html: 'Panel content goes here.'
}
]
},
buttons: [ // A list of footer buttons
{
type: 'submit',
text: 'OK'
}
]},
{ inline: 'toolbar', persistent: true }
});
Example: using focus
to refocus an open but de-focused dialog
Because a dialog with a { persistent: true }
property does not close when the dialog loses focus, it is possible for an end-user to open a further instance of the dialog.
To prevent this
-
add a check that the dialog is already open; and
-
use the
focus
method in theDialogInstanceAPI
to transfer focus to the open dialog rather than creating a new instance of the same dialog.
let dialogOpened = false;
let dialogInstanceApi = null;
const openDialog = () => {
dialogOpened = true;
dialogInstanceApi = editor.windowManager.open({
title: 'Test',
body: {
type: 'panel',
items: [{
type: 'bar',
items: [{
type: 'input',
name: 'name',
placeholder: 'Name',
maximized: true
}
]
}]
},
onClose: () => {
dialogOpened = false;
},
buttons: [{
type: 'cancel',
name: 'cancel',
text: 'Cancel'
}],
initialData: {
name: ''
}
}, {
inline: 'bottom',
persistent: true
});
};
const focusDialog = () => {
dialogInstanceApi.focus('name');
}
editor.ui.registry.addButton('example', {
type: 'button',
text: 'example',
tooltip: 'example',
onAction: () => {
dialogOpened ? focusDialog() : openDialog();
}
});
streamContent
streamContent
is an optional property, available to add to the iframe
dialog component.
The property has a default value of false
.
When streamContent
is set to true
, content presented within the iframe
dialog component is updated using the document.write()
method, rather than by setting the srcdoc
attribute.
Setting the srcdoc
attribute causes the iframe
to reload. This results in a visually jarring flickering effect in most modern browsers, particularly when content is rapidly updating.
As well, performing updates via the srcdoc
attribute means the contents of the iframe
are not accessible. As a consequence, it is not possible to automatically scroll the iframe
contents to the bottom as it gets updated.
Setting streamContent
to true
minimises the flickering effect.
If the iframe
component is already scrolled to the end, streamContent: true
also keeps the view at this point. The UX is content being added to the iframe
component as if it is being quickly typed in.
A user can, however, scroll through the iframe
component as updates are being added. If the view is scrolled back to the end while updates are still being added, the streamContent: true
setting will, again, keep the view at this point.
Type: Boolean
Possible values: true
false
Default value: false
Example: setting an iframe
component to display updating content using the streamContent
property
tinymce.activeEditor.windowManager.open({
title: 'Dialog Title', // The dialog's title - displayed in the dialog header
size: 'normal',
body: {
type: 'panel', // The root body type - a Panel or TabPanel
items: [ // A list of panel components
{
name: 'preview',
type: 'iframe',
streamContent: true
}
]
},
buttons: [ // A list of footer buttons
{
type: 'submit',
text: 'OK'
}
]
}, { inline: 'bottom' } );
Dialog position
The example above also adds a second argument — `{ inline: 'bottom' } — to the dialog. This argument changes the presented position of the dialog within the TinyMCE editor. For information on using this property see the Dialog position section of the Dialog configuration documentation. |
Recommended method for updating content in an iframe
component
The recommended method for updating content in an iframe
component is:
`onAction: (api) => api.setData({ myiframe: 'new content' })`
-
This updates the iframe to contain the string
'new content'
. This text can be any valid html. -
onAction
is a callback defined in the dialog spec. It is called when a button within the dialogbody
is triggered. -
myiframe
is the name of theiframe
component in this spec.
Dialog position
By default a dialog is shown as a modal in the center of the editor viewport.
This presented position can be changed by providing a second argument, with an appropriate value, to editor.windowManager.open()
.
inline
The inline
option, passed to editor.windowManager.open()
, sets the dialog’s presented position to one of two possiblities.
When added to a configuration with the value, toolbar
, it sets the dialog to appear adjacent to the TinyMCE toolbar.
When added to a configuration with the value, bottom
, it sets the dialog to appear at the bottom of the editor viewport.
Type: String
Possible values: toolbar
, bottom
Basic example with the inline argument added and set to toolbar
tinymce.activeEditor.windowManager.open({
title: 'Dialog Title', // The dialog's title - displayed in the dialog header
body: {
type: 'panel', // The root body type - a Panel or TabPanel
items: [ // A list of panel components
{
type: 'htmlpanel', // an HTML panel component
html: 'Panel content goes here.'
}
]
},
buttons: [ // A list of footer buttons
{
type: 'submit',
text: 'OK'
}
]
}, { inline: 'toolbar' });