If you already have an document
object with defined variables, that you saved from the editor, you can open the variable editor by the following function call:
const variableEditorConfig = {
plugin: "variable-editor",
data: { document },
settings: {
hideHeader: false, // hides the header
variablesToEdit: ["varName1", "varName2"], // an array of variable names
buttons: {
header: {
left: [], // an array of objects describing the top left corner buttons of the editor
right: [], // an array of objects describing the top right corner buttons of the editor
},
footer: {
left: [], // an array of objects describing the bottom left corner buttons of the editor
right: [], // an array of objects describing the bottom right corner buttons of the editor
},
textInsert: [], // an array of objects describing the buttons that are added to the inline text editor toolbox
},
fontStacks: [ // an array of arrays, the inner array contains the font families as strings in the font stack
["Poppins", "Helvetica Neue", "Helvetica", "Arial", "sans-serif"]
],
hideDefaultFonts: true, // if true, the default built-in font stacks are hidden, if false, the custom font stacks are added to the default ones.
},
hooks: {}, // an object of available hooks (for example onHeaderButtonClicked)
}
// Fullscreen
const variableEditorInstance = await chamaileonPlugins.createFullscreenPlugin(variableEditorConfig);
// Inline
const variableEditorInstance = await chamaileonPlugins.createInlinePlugin(
variableEditorConfig,
{
container: "#email-variable-editor", /* HTML Element */
dimensions: {
width: 1000, // default 100%
height: 720, // default 100%
scale: 1, // default 1
}
}
);
These will be returned after a successful plugin initialization.
These are methods provided by the plugin instance.
Updates the settings inside the plugin instance on the fly.
const newSettings = {
hideDefaultFonts: false,
fontStacks: [],
}
await variableEditorInstance.methods.updateSettings(newSettings);
Updates the data inside the plugin instance on the fly.
await variableEditorInstance.methods.updateData({ document });
Updates the hooks inside the plugin instance on the fly.
You can read more about the updateHooks
method here.
await variableEditorInstance.methods.updateHooks({ hooks, resetHooks });
This function will resolve the current state of the document as a JSON object.
const document = await variableEditorInstance.methods.getDocument();
Shows the preview instance iframe. Fullscreen mode only.
You can read more about the optionalParams
object here.
await variableEditorInstance.show(optionalParams);
Hides the preview instance iframe. Fullscreen mode only.
await variableEditorInstance.hide();
Shows the splash screen inside the preview instance. Fullscreen mode only.
await variableEditorInstance.showSplashScreen();
Hides the splash screen inside the preview instance. Fullscreen mode only.
variableEditorInstance.hideSplashScreen();
Destroys the preview instance.
await variableEditorInstance.destroy();
Property | Type | Description |
---|---|---|
data | object | The initial data of the plugin instance |
settings | object | The initial settings of the plugin instance |
hooks | object | You can define functions that will be called on different events that occur inside the plugin. For more, please check out the variableEditorConfig.hooks section. |
The data object has the following properties:
Property | Type | Description |
---|---|---|
document | object | The email document. |
The settings object has the following properties:
Property | Type | Description |
---|---|---|
hideHeader | boolean | Hides the plugin header. In inline mode you may want to hide it. |
buttons | object | The configuration of the header, footer and textInsert buttons. |
variablesToEdit | object | An array of variable names that are editable with the plugin. The names must match the already defined variables. |
fontStacks | array | An array of arrays containing the font stacks. |
hideDefaultFonts | boolean | If it's true, the default built-in font stacks are hidden, if it's false, the custom font stacks are added to the default ones. |
You can configure multiple buttons inside the variable editor. You can put multiple buttons in the header and the footer, in both it can be on the left and/or right hand side. You can set up their icons, labels and ids. If a user clicks on them, then the onButtonClicked
hook will be called with the id
of the button. You can also add badges to the buttons as well.
This way, you can even easily configure the variable editor to be a step in a wizard.
Example:
variableEditorConfig.settings.buttons.header = {
left: [
{
id: "close",
icon: "arrow-left", // icons from https://pictogrammers.github.io/@mdi/font/6.7.96/ without the mdi- prefix
color: "#000",
style: "text" // filled, depressed (no shadow filled), outlined, text, plain
},
],
right: [
{
id: "help-center",
label: "Help center",
color: "#000",
style: "text",
badge: {
color: "#bbbbbb",
icon: "lock",
},
},
]
};
variableEditorConfig.settings.buttons.footer = {
left: [
{
id: "prev",
label: "Prev",
style: "outlined"
},
],
right: [
{
id: "next",
label: "Next",
style: "outlined"
},
],
};
You can also configure custom buttons for the CKEditor which is going to be visible when a text variable is edited. You have to add similar objects to the textInsert
array, the only difference is that the icon has to be an actual image.
variableEditorConfig.settings.buttons.textInsert = [
{
id: "merge-tags",
label: "Merge Tags",
icon: "https://raw.githubusercontent.com/ckeditor/ckeditor4/major/skins/kama/icons/paste.png"
},
];
Each and every hook should be an asynchronous process, so all of the hook handler functions have to return Promise
s.
In most cases you just have to resolve the promise when the async operation is done without any params, but in some cases, you will have to resolve certain objects with properties that the plugin can use. Similarly to the parameters, we always expect an object to be resolved, even if it only has one property. (This way it will be easier to add new properties later on if needed.)
If any errors occurred on your side, you can reject the promise with an instance of Error
. In this case, the error message will be shown in a snackbar inside the plugin instance.
function handler(params) {
return new Promise((resolve, reject) => {
// You can put the logic here.
// Resolve the promise when everything is okay
// Reject the promise on error
if (!error) {
resolve(dataToResolve) // In some cases, you don't have to resolve any data. You can resolve the promise without a parameter.
} else {
reject(new Error("Your error message"))
}
})
}
Note that, with the async syntax, the unexpected errors will be also displayed:
async function handler(params) {
// Unexpected errors will also cause promise rejections in this case
// For example, if you get a timeout error, that will also be displayed in a snackbar in the editor.
// Any exception will be caught by the SDK and the message property of the error object will be shown in a snackbar.
return dataToResolve;
}
Below are the list of hooks that you can use. Read more about them in the following sections.
variableEditorConfig.hooks = {
onEditImage,
onTextInsertPluginButtonClicked,
onButtonClicked,
};
This hook is called when the user wants to select an image from the gallery.
/*
Params: nothing.
Has to resolve:
- src: The full url of the selected image
*/
variableEditorConfig.hooks.onEditImage = () => {
return new Promise(resolve => {
// You have to resolve an object with an src prop
resolve({ src });
});
};
This hook is called when the user clicks on one of the textInsert
buttons when editing a text variable.
/*
Params:
- buttonId: id of the button from the variableEditorConfig.settings.buttons.textInsert array
Has to resolve:
- value: The string you want to insert.
Can resolve:
- isHTML: true if the value contains a HTML snippet. Defaults to false.
*/
variableEditorConfig.hooks.onTextInsertPluginButtonClicked = ({ buttonId }) => {
return new Promise(resolve => {
// Here, you can implement your custom dialog
resolve({ value: "Your inserted text.", isHTML: false });
});
};
You can create custom actions with this hook based on your button configuration.
/*
Params:
- buttonId: id of the button from variableEditorConfig.settings.buttons.header or variableEditorConfig.settings.buttons.footer
Has to resolve: nothing.
*/
variableEditorConfig.hooks.onButtonClicked = ({ buttonId }) => {
return new Promise(resolve => {
// Here, you can implement your custom dialog
resolve();
});
};
We put together a demo and you can check out the code here.
There is an advanced example that shows you how you can use the variable editor to create an email creation wizard with which you can easily customize a whole series of emails. Code.
You can also check out the email variable editor plugin on the Chamaileon SDK Playground.