---
title: "Programmatic Template Updates"
description: "Replace the whole template in a running editor with updateTemplate, with optional undo support."
url: https://docs.topol.io/email-editor/guide/update-template.html
---

# Programmatic Template Updates

**`updateTemplate` replaces the entire template in a running editor,** which suits pushing changes in from your application without the user acting.

## Overview

Unlike `load`, which is used when the editor first opens, `updateTemplate` is built for runtime updates while the editor is active. It automatically:

-   Normalizes the template against Topol's schema
-   Creates an undo snapshot (configurable)
-   Marks the template as edited

## Basic usage

```js
// Update template with a template object
window.TopolPlugin.updateTemplate(templateJson);

// Update template from a JSON string
window.TopolPlugin.updateTemplate(JSON.stringify(templateJson));
```

## Options

The `updateTemplate` function accepts an optional second parameter for configuration:

```ts
interface IUpdateTemplateOptions {
  skipSnapshot?: boolean;
}
```

| Option | Type | Default | Description |
| --- | --- | --- | --- |
| `skipSnapshot` | `boolean` | `false` | When `true`, skips creating an undo snapshot before updating |

## Examples

### Standard update (with undo support)

By default, `updateTemplate` creates an undo snapshot before replacing the template. This allows users to undo the programmatic change:

```js
// User can undo this change
window.TopolPlugin.updateTemplate(newTemplate);
```

The undo history holds the ten most recent snapshots, and taking a new one clears anything waiting to be redone.

### Update without undo snapshot

If you don't want the update to be undoable (e.g., when syncing with external state), use the `skipSnapshot` option:

```js
// User cannot undo this change
window.TopolPlugin.updateTemplate(newTemplate, { skipSnapshot: true });
```

### Updating from external source

A common use case is updating the template based on external events:

```js
// Listen for external template updates
socket.on("templateUpdate", (templateData) => {
  window.TopolPlugin.updateTemplate(templateData, { skipSnapshot: true });
});
```

### Template format

**Direct template object:**

```js
const template = {
  tagName: "mj-global-style",
  attributes: {
    /* ... */
  },
  children: [
    /* ... */
  ],
  // ...
};

window.TopolPlugin.updateTemplate(template);
```

**Wrapped format**, which also refreshes the block's feed data:

```js
window.TopolPlugin.updateTemplate({
  template: templateJson,
  feeds: [],
  datafeeds: [],
});
```

## Callbacks

### onTemplateUpdated

Called with no arguments when the template is successfully updated:

```js
const TOPOL_OPTIONS = {
  callbacks: {
    onTemplateUpdated() {
      console.log("Template was updated programmatically");
    },
  },
};
```

### onError

Called with the type `updateTemplate` when a template passed as a **string** cannot be parsed as JSON. For full documentation on the `onError` callback, see [Callbacks](https://docs.topol.io/email-editor/guide/callbacks.html#onerror).

```js
const TOPOL_OPTIONS = {
  callbacks: {
    onError(type, message, responseBody) {
      if (type === "updateTemplate") {
        console.error("Failed to update template:", message);
      }
    },
  },
};
```

`responseBody` stays undefined for this error type, since there is no server response involved.

## Error handling

When a JSON string cannot be parsed:

1.  The `onError` callback is triggered with type `updateTemplate`
2.  A notification is shown to the user
3.  The current template remains unchanged

A template that parses but does not match the schema is treated differently. Rather than being rejected, it is **normalized**: values that fail validation are replaced with valid ones and the update proceeds. Pass a well-formed template if you need the result to match your input exactly.
