This is known to be accurate as of Foundry Core 0.8.x
There is a API wiki Page dedicated to Dialogs
Custom dialog windows are a straightfoward way to interface with users to carry out specific actions or display certain information.
This article aims to walk through the process of creating a custom dialog window from scratch.
This guide is geared towards beginners but can be applied to more complex module development as well.
The Dialog
class is an extension of the Application
class. For our purposes, this just means that the foundation of a dialog window is the same as most of the other windows/UI elements you are already familiar with.
Dialog
instances are intended for basic interfacing. For more complex data handling, consider using FormApplication
.
A custom dialog window is comprised of the following elements:
To create a custom dialog window (an instance of this class), start with the following:
const myDialog = new Dialog({
title: "My Dialog Title",
content: `My dialog content`,
buttons: {}
}).render(true);
Note that without including .render(true)
, the dialog window will not appear (render). The above block will not render any buttons since no buttons were defined. Buttons are covered below.
Assigning the dialog to a variable (e.g. myDialog
) is not necessary but would allow you to render the dialog window later in your code if you desired: myDialog.render(true)
.
The body of a dialog window is defined by the content
property. This is a string of HTML which can be defined during dialog creation as shown above. As it is just HTML, styling can be defined in the content as well:
const myContent = `
<style>
.my-class {
color: blue
}
</style>
<div class="my-class">
This will now appear blue!
</div>
`;
new Dialog({
title: "My Dialog Title",
content: myContent,
buttons: {}
}).render(true);
While content HTML can be defined manually as above, a popular method for creating HTML content is through the use of templates. This requires a separate .html
or .hbs
file and for the template rendering to be called in an async function:
const myContent = await renderTemplate("modules/myModule/templates/myTemplate.html", data);
new Dialog({
title: "My Custom Dialog Title",
content: myContent,
buttons: {}
}).render(true);
Dialog buttons are comprised of the following elements:
Each button is defined as an object within the buttons
property:
new Dialog({
title: "My Dialog Title",
content: "My dialog content",
buttons: {
button1: {
label: "Button #1",
callback: () => {ui.notifications.info("Button #1 Clicked!")},
icon: `<i class="fas fa-check"></i>`
},
button2: {
label: "Button #2",
callback: () => {ui.notifications.info("Button #2 Clicked!")},
icon: `<i class="fas fa-times"></i>`
}
}
}).render(true);
Each button has a callback function which is run when the button is clicked. This function can be defined during dialog creation as above, or can be a set to a pre-defined function:
function myCallback() {
ui.notifications.info("Button #1 Clicked!");
}
new Dialog({
title: "My Dialog Title",
content: "My dialog content",
buttons: {
button1: {
label: "Button #1",
callback: () => myCallback(),
icon: `<i class="fas fa-check"></i>`
}
}
}).render(true);
Note that the callback must be provided in the form: () => {}
or myCallback.bind(this)
.
As with any function, callbacks can be provided arguments to be used during their execution. A helpful argument is html
, which provides the callback with the HTML content of the dialog at time of execution (when the button is clicked). This content is provided in a jQuery
object (as of core version 0.8.6
):
const myContent = `
Value:
<input id="myInputID" type="number" value="0" />
`;
new Dialog({
title: "My Dialog Title",
content: myContent,
buttons: {
button1: {
label: "Display Value",
callback: (html) => myCallback(html),
icon: `<i class="fas fa-check"></i>`
}
}
}).render(true);
function myCallback(html) {
const value = html.find("input#myInputID").val();
ui.notifications.info(`Value: ${value}`);
}
A special type of callback that is not associated with a button is the close
callback. This function is called when the dialog window closes, no matter how this closure was initiated (via a button click, escape key press, or close header button click):
new Dialog({
title: "My Dialog Title",
content: "My dialog content",
buttons: {},
close: () => {ui.notifications.info("My dialog was closed!")}
}).render(true);
A similar operation can be done when the dialog is rendered using render
:
new Dialog({
title: "My Dialog Title",
content: "My dialog content",
buttons: {},
render: () => {ui.notifications.info("My dialog was rendered!")}
}).render(true);
Icons can be selected from fontawesome.com. Simply copy the HTML provided at the top of each icon page.
A button can be assigned as "default" meaning it will be "clicked" when the enter key is pressed:
new Dialog({
title: "My Dialog Title",
content: "My dialog content",
buttons: {
button1: {
label: "Button #1",
callback: () => {ui.notifications.info("Button #1 Clicked!")},
icon: `<i class="fas fa-check"></i>`
},
button2: {
label: "Button #2",
callback: () => {ui.notifications.info("Button #2 Clicked!")},
icon: `<i class="fas fa-times"></i>`
}
},
default: "button1"
}).render(true);
Note that the value for the default
key is a string.
As with all Appliaction
instances, additional options can be provided during dialog creation to adjust parameters such as window size and position:
const myDialogOptions = {
width: 200,
height: 400,
top: 500,
left: 500
};
new Dialog({
title: "My Dialog Title",
content: "My dialog content",
buttons: {}
}, myDialogOptions).render(true);
For a full list of options, see the Application
class in foundry.js
.
The Dialog
class provides two built-in helper methods to quickly create dialogs.
Note that these are static methods of the Dialog
class, and so they are called on Dialog
itself, not a new instance of the class (i.e. do not use new
).
Dialog.confirm({
title: "My Confirm Dialog Title",
content: "My confirm dialog content",
yes: () => {ui.notifications.info("Yes was pressed!")},
no: () => {ui.notifications.info("No was pressed!")},
defaultYes: false
});
Dialog.prompt({
title: "My Prompt Dialog Title",
content: "My prompt dialog content",
label: "My Prompt Button Label",
callback: () => {ui.notifications.info("Prompt button pressed!")}
});