Email Variable Editor Plugin

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
		}
	}
);

Variable editor instance functions

These will be returned after a successful plugin initialization.

variableEditorInstance.methods

These are methods provided by the plugin instance.

variableEditorInstance.methods.updateSettings

Updates the settings inside the plugin instance on the fly.

const newSettings = {
	hideDefaultFonts: false,
	fontStacks: [],
}

await variableEditorInstance.methods.updateSettings(newSettings);

variableEditorInstance.methods.updateData

Updates the data inside the plugin instance on the fly.

await variableEditorInstance.methods.updateData({ document });

variableEditorInstance.methods.updateHooks

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 });

variableEditorInstance.methods.getDocument

This function will resolve the current state of the document as a JSON object.

const document = await variableEditorInstance.methods.getDocument();

variableEditorInstance.show

Shows the preview instance iframe. Fullscreen mode only.

You can read more about the optionalParams object here.

await variableEditorInstance.show(optionalParams);

variableEditorInstance.hide

Hides the preview instance iframe. Fullscreen mode only.

await variableEditorInstance.hide();

variableEditorInstance.showSplashScreen

Shows the splash screen inside the preview instance. Fullscreen mode only.

await variableEditorInstance.showSplashScreen();

variableEditorInstance.hideSplashScreen

Hides the splash screen inside the preview instance. Fullscreen mode only.

variableEditorInstance.hideSplashScreen();

variableEditorInstance.destroy

Destroys the preview instance.

await variableEditorInstance.destroy();

Variable editor configuration

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.

variableEditorConfig.data

The data object has the following properties:

Property Type Description
document object The email document.

variableEditorConfig.settings

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.

variableEditorConfig.settings.buttons

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"
	},
];

variableEditorConfig.hooks

Each and every hook should be an asynchronous process, so all of the hook handler functions have to return Promises.

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,
};

variableEditorConfig.hooks.onEditImage

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 });
	});
};

variableEditorConfig.hooks.onTextInsertPluginButtonClicked

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 });
	});
};

variableEditorConfig.hooks.onButtonClicked

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();
	});
};

Examples

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.