Callbacks
The Topol Plugin provides a powerful and flexible callback system that allows you to integrate seamlessly with your own application logic. This system enables event-driven communication from the editor (“callbacks up”) while your settings and configuration are passed into the editor (“props down”).
By defining a set of callback functions inside the TOPOL_OPTIONS object, you can respond to editor events such as save actions, file uploads, test email sends, undo/redo changes, and even error states.
All callbacks are optional, and you can include only the ones you need. Together, they give you full programmatic control over how your application responds to editor activity.
How to use Callbacks
Callbacks are defined inside the TOPOL_OPTIONS configuration like this:
const TOPOL_OPTIONS = {
// other options...
callbacks: {
onSave(json, html, mutations) {
// Handle save logic
},
onInit(json, html) {
// Handle editor initialization
},
// more callbacks...
},
};Available Callbacks and their Usage
()
Triggered when the Save button is clicked or when TopolPlugin.save() is called manually.
Use this to save the template data (json) and its HTML output (html) to your backend or local storage. The mutations parameter is used only by the Multilingual Template feature. If you are not using this feature, it will be an empty array and you can ignore it.
The email subject line is accessible from the json parameter at json.attributes["mj-subject"].text. When using multilingual templates, per-language subject lines are stored in json.langs[].translations["mj-subject"].content.
const TOPOL_OPTIONS = {
callbacks: {
onSave(json, html, mutations) {
// save json and html to your infrastructure.
// save mutations only if using Multilingual Templates.
},
},
};()
Called when the Save and Close button is clicked in the editor Top Bar.
Use this for saving and then exiting the editor or redirecting the user.
const TOPOL_OPTIONS = {
callbacks: {
onSaveAndClose(json, html) {
// save json and html to your infrastructure and close the editor
},
},
};()
Fires when a user sends a test email from the preview screen.
When testingEmails is set to true, the email parameter will always be an array of emails.
You can use this callback to send test emails using your own service (e.g., SendGrid, Mailgun, custom SMTP).
const TOPOL_OPTIONS = {
callbacks: {
onTestSend(email, json, html) {
// send a test email using your preferred sender
},
},
};()
Called when a user clicks “Choose a file” inside image or video properties.
Use this to trigger your custom file manager UI. You can read more about the feature here.
const TOPOL_OPTIONS = {
callbacks: {
onOpenFileManager() {
// open your custom filemanager dialog window
},
},
};()
Executed when the editor is fully initialized.
Commonly used to hide loading spinners or initialize user tracking once the editor is ready.
const TOPOL_OPTIONS = {
callbacks: {
onInit(json, html) {
// hide the loader or track the usage
},
},
};()
Fires after calling TopolPlugin.load(YOUR_TEMPLATE) and the template is fully rendered.
const TOPOL_OPTIONS = {
callbacks: {
onLoaded(json, html) {
// hide the loader
},
},
};()
Fires after calling TopolPlugin.updateTemplate(YOUR_TEMPLATE) and the template is successfully updated.
const TOPOL_OPTIONS = {
callbacks: {
onTemplateUpdated() {
// template was updated programmatically
},
},
};()
Triggered when a user saves a content block to their personal library.
Use this to store the block definition on your own infrastructure. You can read more here.
const TOPOL_OPTIONS = {
callbacks: {
onBlockSave(block) {
// save the block on your infrastructure
},
},
};()
Fires when a user removes a saved block. You can read more here.
const TOPOL_OPTIONS = {
callbacks: {
onBlockRemove(blockId) {
// remove the block on your infrastructure
},
},
};()
Called when a user edits an existing saved block. You can read more here.
const TOPOL_OPTIONS = {
callbacks: {
onBlockEdit(blockId) {
// edit the block on your infrastructure
},
},
};()
Fired when the Undo button is used. count indicates how many steps have been undone.
const TOPOL_OPTIONS = {
callbacks: {
onUndoChange(count) {
// ...
},
},
};()
Fired when the Redo button is clicked. count shows the number of steps redone.
const TOPOL_OPTIONS = {
callbacks: {
onRedoChange(count) {
// ...
},
},
};()
Called when the user enters the Preview mode.
const TOPOL_OPTIONS = {
callbacks: {
onPreview(html) {
// ...
},
},
};()
If built-in notifications are disabled using disableAlerts: true, then this callback allows you to replace them with your own alert system.
You read more about the custom alerts here.
const TOPOL_OPTIONS = {
callbacks: {
onAlert(notification) {
//use your own notification, or create proxy for built-in notifications
},
},
};()
Fires when the editor encounters an unrecoverable error. Useful for diagnostics and fallbacks.
There are 4 types of errors:
templateLoad- Indicates that the JSON of the template is not correct and editor cannot read it correctly.network- Indicates that network issue happened during internal or external (endpoints given in API property inTOPOL_OPTIONS) Fetch/XHR calls.authorize- Invalid API key or wrong/unverified domainupdateTemplate- Indicates that the template passed toTopolPlugin.updateTemplate()could not be parsed (invalid JSON)
The optional third parameter responseBody (unknown) contains the raw parsed response body from your server (error.response.data). It is available for all HTTP error responses (4xx, 5xx) and is undefined for network errors where no response was received. If your backend returns JSON, you will receive the parsed object directly.
const TOPOL_OPTIONS = {
callbacks: {
onError(type, message, responseBody) {
if (type === "network") { // templateLoad | network | authorize | updateTemplate
console.log("Network issue: " + message);
// Access custom error data from your backend
if (responseBody?.errors) {
responseBody.errors.forEach((err) => {
TopolPlugin.createNotification({
text: err.detail,
type: "error",
});
});
}
}
},
},
};Language State Callbacks
These callbacks allow you to synchronize external UI with the editor's Multilingual Templates state. They fire whenever a language mutation is created, deleted, selected, or when the primary language changes — both from the built-in UI and from programmatic API calls.
()
Triggered when a new language mutation is created, either via the editor UI or by calling TopolPlugin.createLanguage(lang).
lang— the language code of the newly created mutation (e.g."fr")mutations— the updated array of all mutations after the creation
const TOPOL_OPTIONS = {
callbacks: {
onLanguageCreated(lang, mutations) {
console.log(`Language "${lang}" created. Current mutations:`, mutations);
// Update your external language selector
},
},
};()
Triggered when a language mutation is deleted. Deletion always requires user confirmation via a modal dialog, whether initiated from the UI or via TopolPlugin.deleteLanguage(lang).
lang— the language code of the deleted mutationmutations— the updated array of all remaining mutations after the deletion
const TOPOL_OPTIONS = {
callbacks: {
onLanguageDeleted(lang, mutations) {
console.log(`Language "${lang}" deleted. Remaining mutations:`, mutations);
// Update your external language selector
},
},
};()
Triggered when the active editing language changes, either via the editor UI dropdown or by calling TopolPlugin.selectLanguage(lang). Does not fire if the requested language is already active or does not exist.
lang— the language code of the newly active mutation
const TOPOL_OPTIONS = {
callbacks: {
onLanguageSelected(lang) {
console.log(`Switched to language "${lang}"`);
// Highlight the active language in your external UI
},
},
};()
Triggered when the primary language is changed via the editor UI or by calling TopolPlugin.setPrimaryLanguage(lang). If the language does not yet exist, it will be created first (firing onLanguageCreated as well).
lang— the language code of the new primary mutationmutations— the updated array of all mutations reflecting the new primary assignment
const TOPOL_OPTIONS = {
callbacks: {
onPrimaryLanguageChanged(lang, mutations) {
console.log(`Primary language changed to "${lang}"`);
// Update your external UI to reflect the new primary
},
},
};()
Triggered when TopolPlugin.getMutations() is called. Returns the current list of all language mutations without modifying any state.
mutations— array of all current mutations, each withlang(string) andprimary(boolean)
const TOPOL_OPTIONS = {
callbacks: {
onGetMutations(mutations) {
console.log("Current mutations:", mutations);
// Use this data to populate your external language selector
},
},
};