Templates plugin
This plugin is only available for paid TinyMCE subscriptions. |
This feature is only available for TinyMCE 6.4 and later. |
As of TinyMCE 7.0, the Advanced Template plugin has been renamed to Templates. When adding Templates in your editor, continue to use advtemplate. |
The Templates Premium plugin enables the creation of complex, interactive templates using TinyMCE.
They can also be added to a TinyMCE instance by end-users selecting content in a TinyMCE document and saving the selection as a template via the TinyMCE user-interface.
Templates does not support template editing. To update a particular template; insert the template into an editor; make edits; select the, now edited, content; and then create a new template (using, for example, the Tools > Save as Template… menu item). |
Using the Templates plugin
Inserting a template
To insert a template
-
Select Template… from the Insert menu or Select the Insert template toolbar button.
-
Select the template to add to the TinyMCE document from the Templates dialog that presents.
-
Click Insert or press Return.
Adding a new template
To add a new template
-
Select the material in the TinyMCE document that is going to be the new template and
-
Save the template using one of the following methods:
-
Select Save as template… from the Tools menu.
-
Select Save as template… from the context menu.
-
Select the Save as template toolbar button.
-
Then, in the New template dialog that presents
-
Enter a name for the new template in the Template name field;
-
Select a category for the new template from the Category pop-up menu; and
-
Click Save or press Return.
Adding a new category
To add a new category
-
Select Template… from the Insert menu to open the Templates dialog.
-
Click on the New category button in the dialog footer.
-
The New category form will pop up within the editor.
-
In the New category form, enter the name of the new category you want to add.
-
Click the Save button to submit the form.
-
After saving, the new category will appear in the Tree component of the Templates dialog.
Searching for templates
To search for a template
-
Select Template… from the Insert menu to open the Templates dialog.
-
Enter the name of the template you are searching for in the Search field.
-
As you type, the displayed list of matching templates updates in real-time in the dialog’s Tree component.
Template list management
To manage the template list
-
Select Template… from the Insert menu to open the Templates dialog.
-
Select the template or the category you want to modify.
-
Click on the three dots menu for the selected item.
The actions menu will open. -
From the actions menu, choose the appropriate operation based on your requirements:
-
Rename category/template.
-
Move template to another category.
-
Move all category items to another category.
-
Delete template/category.
-
Readonly categories
This feature is only available for TinyMCE 7.4 and later. |
Templates categories can be set to read-only in TinyMCE, preventing users from modifying the category or its templates. When a category is set to read-only, users cannot:
-
add new templates to the category
-
delete the category or its templates
-
rename the category or its templates
-
move templates into or out of the category
A lock icon visually indicates that a category is read-only, preventing users from modifying the category or its templates through the user interface.
To create a locked (read-only) category, add the locked: true
property to the category object in your templates data:
{
title: 'Locked Templates',
locked: true, // Locks the category as readonly
items: [
{
title: 'How to find model number',
content: '<p dir="ltr">Hi {{Customer.FirstName}},</p>\n<p>...</p>'
},
{
title: 'Support escalation',
content: '<p dir="ltr">Hi {{Customer.FirstName}},</p>\n<p>...</p>'
}
]
}
-
TinyMCE
-
HTML
-
JS
<textarea id="readonly-locked-template">
<h3 style="font-size: 1.5em; margin: 20px 0;">Working with Templates</h3>
<h4 style="font-size: 1.25em; margin: 15px 0;">Inserting a template</h4>
<p style="margin: 10px 0;">To insert a template:</p>
<ol style="margin-left: 20px;">
<li>Click the <strong>Insert template</strong> toolbar button or select <strong>Insert template...</strong> from the <strong>Insert</strong> menu.</li>
<li>In the <strong>Templates</strong> dialog, you'll see different categories:
<ul style="margin-left: 20px;">
<li>Regular categories with editable templates</li>
<li>Locked categories (marked with a 🔒 icon) containing read-only templates</li>
</ul>
</li>
<li>Select any template to preview its content.</li>
<li>Click <strong>Insert</strong> or press <strong>Return</strong> to add the template to your document.</li>
</ol>
<div style="margin: 15px 0; padding: 10px 15px; border-left: 4px solid #3498db; background-color: #f0f7fb;">
<p><strong>Note:</strong> Templates in locked categories cannot be modified, but they can still be inserted into your document.</p>
</div>
<h4 style="font-size: 1.25em; margin: 15px 0;">Adding a new template</h4>
<p style="margin: 10px 0;">To add a new template:</p>
<ol style="margin-left: 20px;">
<li>Select the content in your document that you want to save as a template.</li>
<li>Click the <strong>Save as template</strong> toolbar button or select <strong>Save as template…</strong> from the <strong>Tools</strong> menu.</li>
<li>In the <strong>New template</strong> dialog:
<ol style="margin-left: 20px;">
<li>Enter a name for your template in the <strong>Template name</strong> field.</li>
<li>Choose a category from the <strong>Category</strong> dropdown menu.
<div style="margin: 15px 0; padding: 10px 15px; border-left: 4px solid #e74c3c; background-color: #fdf7f7;">
<p><strong>Important:</strong> Locked categories (marked with a 🔒 icon) are read-only. You cannot save new templates to these categories.</p>
</div>
</li>
<li>Click <strong>Save</strong> or press <strong>Return</strong>.</li>
</ol>
</li>
</ol>
<h4 style="font-size: 1.25em; margin: 15px 0;">Managing Templates</h4>
<p style="margin: 10px 0;">When working with templates, keep in mind:</p>
<ul style="margin-left: 20px;">
<li>Templates in regular categories can be edited, renamed, or deleted.</li>
<li>Templates in locked categories (🔒) are read-only and cannot be:
<ul style="margin-left: 20px;">
<li>Modified or renamed</li>
<li>Deleted</li>
<li>Moved to different categories</li>
</ul>
</li>
</ul>
</textarea>
const headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
};
const handleResponse = (message) => (response) => {
if (!response.ok) {
return response.text().then((error) => {
console.error(error);
throw new Error(message);
});
}
return response.json();
};
const advtemplate_list = () =>
fetch('/categories', {
method: 'GET',
headers,
}).then(handleResponse('Failed to get template list'));
const advtemplate_get_template = (id) =>
fetch(`/templates/${id}`, {
method: 'GET',
headers,
}).then(handleResponse('Failed to get template'));
const advtemplate_create_category = (title) =>
fetch('/categories', {
method: 'POST',
body: JSON.stringify({ title }),
headers,
}).then(handleResponse('Failed to create category'));
const advtemplate_create_template = (title, content, categoryId) =>
fetch('/templates', {
method: 'POST',
body: JSON.stringify({ title, content, categoryId }),
headers,
}).then(handleResponse('Failed to create template'));
const advtemplate_rename_category = (id, title) =>
fetch(`/categories/${id}`, {
method: 'PUT',
body: JSON.stringify({ title }),
headers,
}).then(handleResponse('Failed to rename category'));
const advtemplate_rename_template = (id, title) =>
fetch(`/templates/${id}`, {
method: 'PUT',
body: JSON.stringify({ title }),
headers,
}).then(handleResponse('Failed to rename template'));
const advtemplate_delete_template = (id) =>
fetch(`/templates/${id}`, {
method: 'DELETE',
headers,
}).then(handleResponse('Failed to delete template'));
const advtemplate_delete_category = (id) =>
fetch(`/categories/${id}`, {
method: 'DELETE',
headers,
}).then(handleResponse('Failed to delete category'));
const advtemplate_move_template = (id, categoryId) =>
fetch(`/templates/${id}`, {
method: 'PATCH',
body: JSON.stringify({ categoryId }),
headers,
}).then(handleResponse('Failed to move template'));
const advtemplate_move_category_items = (id, categoryId) =>
fetch(`/categories/${id}`, {
method: 'PATCH',
body: JSON.stringify({ categoryId }),
headers,
}).then(handleResponse('Failed to move all templates to new category'));
tinymce.init({
selector: 'textarea#readonly-locked-template',
plugins: [
'advlist', 'anchor', 'autolink', 'charmap', 'code', 'fullscreen',
'help', 'image', 'insertdatetime', 'link', 'lists', 'media',
'preview', 'searchreplace', 'table', 'visualblocks', 'advtemplate'
],
contextmenu: 'advtemplate',
toolbar: 'addtemplate inserttemplate | undo redo | styles | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image',
advtemplate_list,
advtemplate_get_template,
advtemplate_create_category,
advtemplate_create_template,
advtemplate_rename_category,
advtemplate_move_category_items,
advtemplate_delete_category,
advtemplate_rename_template,
advtemplate_move_template,
advtemplate_delete_template,
});
Basic setup
To setup the Templates plugin user-interface in the editor:
-
add
advtemplate
to theplugins
option in the editor configuration; -
add
inserttemplate
andaddtemplate
to thetoolbar
option in the editor configuration; -
add each Templates option to the editor configuration;
tinymce.init({
selector: 'textarea', // change this value according to your html
plugins: "advtemplate",
toolbar: "inserttemplate addtemplate",
contextmenu: "advtemplate",
// Each of the following options must be defined as
// a function that returns a Promise.
// Please find the specific details for each option below.
advtemplate_list,
advtemplate_get_template,
advtemplate_create_category,
advtemplate_create_template,
advtemplate_rename_category,
advtemplate_rename_template,
advtemplate_delete_template,
advtemplate_delete_category,
advtemplate_move_template,
advtemplate_move_category_items
});
The undefined options in the above example must be defined. See the Options below for specific details on each function. |
Interactive examples
There are two approaches to using the Templates Premium plugin: fixed template lists and user-modifiable template lists.
Fixed template lists
For users who work with a fixed template list that does not require modification, you can provide a list directly through the TinyMCE init configuration using the advtemplate_templates
option.
The following interactive predefined list example provides guidance for this approach.
Configuring the Templates plugin to use a static list of predefined templates.
-
TinyMCE
-
HTML
-
JS
-
Edit on CodePen
<textarea id="template-predefined">
<h3>Inserting a template</h3>
<p>To insert a template:</p>
<ol>
<li>select <strong>Template…</strong> from the <strong>Insert</strong> menu or<br />
select the <strong>Insert template</strong> toolbar button.</li>
<li>select the template to add to the TinyMCE document from the <strong>Templates</strong> dialog that presents.</li>
<li>click <strong>Insert</strong> or press <strong>Return</strong>.</li>
</ol>
</textarea>
const advtemplate_templates = [
{
title: 'Quick replies',
items: [
{
title: 'Message received',
content: '<p dir="ltr">Hey {{Customer.FirstName}}!</p>\n<p dir="ltr">Just a quick note to say we’ve received your message, and will get back to you within 48 hours.</p>\n<p dir="ltr">For reference, your ticket number is: {{Ticket.Number}}</p>\n<p dir="ltr">Should you have any questions in the meantime, just reply to this email and it will be attached to this ticket.</p>\n<p><strong> </strong></p>\n<p dir="ltr">Regards,</p>\n<p dir="ltr">{{Agent.FirstName}}</p>'
},
{
title: 'Thanks for the feedback',
content: '<p dir="ltr">Hi {{Customer.FirstName}},</p>\n<p dir="ltr">We appreciate you taking the time to provide feedback on {{Product.Name}}.</p>\n<p dir="ltr">It sounds like it wasn’t able to fully meet your expectations, for which we apologize. Rest assured our team looks at each piece of feedback and uses it to decide what to focus on next with {{Product.Name}}.</p>\n<p dir="ltr"><strong> </strong></p>\n<p dir="ltr">All the best, and let us know if there’s anything else we can do to help.</p>\n<p dir="ltr">-{{Agent.FirstName}}</p>'
},
{
title: 'Still working on case',
content: '<p dir="ltr">Hi {{Customer.FirstName}},</p>\n<p dir="ltr">Just a quick note to let you know we’re still working on your case. It’s taking a bit longer than we hoped, but we’re aiming to get you an answer in the next 48 hours.</p>\n<p dir="ltr">Stay tuned,</p>\n<p dir="ltr">{{Agent.FirstName}}</p>'
}
]
},
{
title: 'Closing tickets',
items: [
{
title: 'Closing ticket',
content: '<p dir="ltr">Hi {{Customer.FirstName}},</p>\n<p dir="ltr">We haven’t heard back from you in over a week, so we have gone ahead and closed your ticket number {{Ticket.Number}}.</p>\n<p dir="ltr">If you’re still running into issues, not to worry, just reply to this email and we will re-open your ticket.</p>\n<p><strong> </strong></p>\n<p dir="ltr">All the best,</p>\n<p dir="ltr">{{Agent.FirstName}}</p>'
},
{
title: 'Post-call survey',
content: '<p dir="ltr">Hey {{Customer.FirstName}}!</p>\n<p dir="ltr"> </p>\n<p dir="ltr">How did we do?</p>\n<p dir="ltr">If you have a few moments, we’d love you to fill out our post-support survey: {{Survey.Link}}</p>\n<p><strong> </strong></p>\n<p dir="ltr">Thanks in advance!<br>{{Company.Name}} Customer Support</p>'
}
]
},
{
title: 'Product support',
items: [
{
title: 'How to find model number',
content: '<p dir="ltr">Hi {{Customer.FirstName}},</p>\n<p><strong> </strong></p>\n<p dir="ltr">My name is {{Agent.FirstName}} and I will be glad to assist you today.</p>\n<p dir="ltr">To troubleshoot your issue, we first need your model number, which can be found on the underside of your product beneath the safety warning label. </p>\n<p dir="ltr">It should look something like the following: XX.XXXXX.X</p>\n<p dir="ltr">Once you send it over, I will advise on next steps.</p>\n<p><strong> </strong></p>\n<p dir="ltr">Thanks!</p>\n<p dir="ltr">{{Agent.FirstName}}</p>'
},
{
title: 'Support escalation',
content: '<p dir="ltr">Hi {{Customer.FirstName}},</p>\n<p dir="ltr">We have escalated your ticket {{Ticket.Number}} to second-level support.</p>\n<p dir="ltr">You should hear back from the new agent on your case, {{NewAgent.FirstName}}, shortly.</p>\n<p><strong> </strong></p>\n<p dir="ltr">Thanks,</p>\n<p dir="ltr">{{Company.Name}} Customer Support</p>'
}
]
}
];
tinymce.init({
selector: "textarea#template-predefined",
plugins: [
"advlist", "anchor", "autolink", "charmap", "code", "fullscreen",
"help", "image", "insertdatetime", "link", "lists", "media",
"preview", "searchreplace", "table", "visualblocks", "advtemplate"
],
contextmenu: 'advtemplate',
toolbar: "inserttemplate undo redo | styles | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",
advtemplate_templates
});
User-modifiable template lists
If the intention is for the template list to be end-user modifiable, the Templates plugin should be configured with options to enable communication with a remote Template storage service.
The following interactive remote storage configuration example provides guidance on configuring the Templates plugin to support user-modifiable template lists.
Configuring the Templates plugin to interact with a remote backend service via REST API.
-
TinyMCE
-
HTML
-
JS
<textarea id="template">
<h3>Inserting a template</h3>
<p>To insert a template</p>
<ol>
<li>select <strong>Insert template...</strong> from the <strong>Insert</strong> menu or<br />
select the <strong>Insert template</strong> toolbar button.</li>
<li>select the template to add to the TinyMCE document from the <strong>Templates</strong> dialog that presents.</li>
<li>click <strong>Insert</strong> or press <strong>Return</strong>.</li>
</ol>
<h3>Adding a new template</h3>
<p>To add a new template</p>
<ol>
<li>select the material in the TinyMCE document that is going to be the new template and</li>
<li>select <strong>Save as template…</strong> from the <strong>Tools</strong> menu or<br />
select the <strong>Save as template</strong> toolbar button.</li>
</ol>
<p>Then, in the <strong>New template</strong> dialog that presents
<ol>
<li>enter a name for the new template in the <strong>Template name</strong> field;</li>
<li>select a category for the new template from the <strong>Category</strong> pop-up menu; and</li>
<li>click <strong>Save</strong> or press <strong>Return</strong>.</li>
</ol>
</textarea>
const headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
const handleResponse = (message) => (response) => {
if (!response.ok) {
response.text().then((message) => console.error(message))
throw new Error(message);
} else {
return response.json();
}
}
const advtemplate_list = () => {
return fetch('/categories', {
method: 'GET',
headers,
})
.then(handleResponse('Failed to get template list'))
}
const advtemplate_get_template = (id) => {
return fetch('/templates/' + id, {
method: 'GET',
headers,
})
.then(handleResponse('Failed to get template'))
}
const advtemplate_create_category = (title) => {
return fetch('/categories', {
method: 'POST',
body: JSON.stringify({
title
}),
headers,
})
.then(handleResponse('Failed to create category'))
}
const advtemplate_create_template = (title, content, categoryId) => {
return fetch('/templates', {
method: 'POST',
body: JSON.stringify({
title,
content,
categoryId
}),
headers,
})
.then(handleResponse('Failed to create template'))
}
const advtemplate_rename_category = (id, title) => {
return fetch('/categories/' + id, {
method: 'PUT',
body: JSON.stringify({
title
}),
headers,
})
.then(handleResponse('Failed to rename category'))
}
const advtemplate_rename_template = (id, title) => {
return fetch('/templates/' + id, {
method: 'PUT',
body: JSON.stringify({
title
}),
headers,
})
.then(handleResponse('Failed to rename template'))
}
const advtemplate_delete_template = (id) => {
return fetch('/templates/' + id, {
method: 'DELETE',
headers,
})
.then(handleResponse('Failed to delete template'))
}
const advtemplate_delete_category = (id) => {
return fetch('/categories/' + id, {
method: 'DELETE',
headers,
})
.then(handleResponse('Failed to delete category'))
}
const advtemplate_move_template = (id, categoryId) => {
return fetch('/templates/' + id, {
method: 'PATCH',
body: JSON.stringify({
categoryId
}),
headers,
})
.then(handleResponse('Failed to move template'))
}
const advtemplate_move_category_items = (id, categoryId) => {
return fetch('/categories/' + id, {
method: 'PATCH',
body: JSON.stringify({
categoryId
}),
headers,
})
.then(handleResponse('Failed to move all templates to new category'))
}
tinymce.init({
selector: "textarea#template",
plugins: [
"advlist", "anchor", "autolink", "charmap", "code", "fullscreen",
"help", "image", "insertdatetime", "link", "lists", "media",
"preview", "searchreplace", "table", "visualblocks", "advtemplate"
],
contextmenu: 'advtemplate',
toolbar: "addtemplate inserttemplate | undo redo | styles | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",
advtemplate_list,
advtemplate_get_template,
advtemplate_create_category,
advtemplate_create_template,
advtemplate_rename_category,
advtemplate_rename_template,
advtemplate_delete_template,
advtemplate_delete_category,
advtemplate_move_template,
advtemplate_move_category_items
});
The insertion point marker
This feature is only available for TinyMCE 6.7 and later. |
The insertion point marker is a fixed string for adding to any template.
The string to add is as follows: {{mce-cursor}}
.
Wherever this string is within a template is where the insertion point appears when that template is added to a TinyMCE document.
Also, and as shown in the interactive demonstration below, the Merge Tags plugin knows to ignore this fixed string, making it possible to use the insertion point marker in conjunction with both plugins.
-
TinyMCE
-
HTML
-
JS
-
Edit on CodePen
<textarea id="template-insertionpoint">
<h3>Using the Insertion Point Marker with Templates (and Merge Tags)<h3>
<h4>To insert a template</h4>
<ol>
<li>
Select <strong>Template…</strong> from the <strong>Insert</strong> menu or<br />
select the <strong>Insert template</strong> toolbar button.
</li>
<li>
Select the template to add to the TinyMCE document from the <strong>Templates</strong> dialog that presents.
<ol>
<li>
Click the <strong>Without an insertion point marker</strong> category to see and select a template that does not use the <code>{{mce-cursor}}</code> insertion point marker.
</li>
<li>
Click the <strong>With an insertion point marker</strong> category to see and select a template that does use the <code>{{mce-cursor}}</code> insertion point marker.
</li>
</ol>
</li>
<li>click <strong>Insert</strong> or press <strong>Return</strong>.</li>
</ol>
<h4>Noting the difference</h4>
<p>The <em>Name entry prompt</em> template without the <code>{{mce-cursor}}</code> insertion point marker, places the insertion point at the end of the template text.</p>
<p>By contrast, the <em>Name entry prompt</em> template with the <code>{{mce-cursor}}</code> insertion point marker places the insertion point at the right spot for someone to enter their name, as requested.</p>
<p>Similarly, the <em>Letter outline</em> template without the <code>{{mce-cursor}}</code> insertion point marker, places the insertion point at the end of the template text.</p>
<p>And, by equivalent contrast, the <em>Letter outline</em> template with the <code>{{mce-cursor}}</code> insertion point marker places the insertion point at the right spot for someone to start writing a letter.</p>
<h4>Working with Merge Tags</h4>
<p>The second pre-defined template in this demonstration — the <em>Letter outline</em> template — shows the <code>{{mce-cursor}}</code> string working in conjunction with the <a href="https://tiny.cloud/docs/tinymce/6/mergetags/">Merge Tags</a> Premium plugin.</p>
<p>The fixed string that is the Insertion Point Marker uses the same delimiting characters as are used by default by the Merge Tags plugin.</p>
<p>The <strong>Merge Tags</strong> plugin knows nothing about the <code>{{mce-cursor}}</code> being a marker string for the <strong>Templates</strong> plugin. And, if this particular string was used in a Merge Tags configuration, the <strong>Merge Tags</strong> plugin would recognise it and substitute it with whatever contents it was set to substitute, as expected.
<p>The <strong>Templates</strong> plugin removes the Insertion Point Marker before inserting a template containing the string in to a TinyMCE instance, however.</p>
<p>Consequently the <strong>Templates</strong> insertion point marker string is never seen by the <strong>Merge Tags</strong> plugin.</p>
</textarea>
tinymce.init({
selector: "textarea#template-insertionpoint",
plugins: [ "advtemplate", "mergetags", ],
toolbar: "inserttemplate | mergetags",
advtemplate_templates: [
{
title: 'Without an insertion point marker',
items: [
{
title: 'Name entry prompt',
content: '<p><strong>Enter your name:</strong></p><p><em>Include both your given and family names, in your preferred order.</em></p>'
},
{
title: 'Letter outline',
content: '<p>{{Current.Date}}</p><p>{{Honorific}} {{Person.Name.Last}},</p><p></p><p> </p><p>Regards,</p><p>{{staff.digital.signature}}</p><p>{{Staff.Name}}</p><p>{{Staff.Email}}</p>'
},
],
},
{
title: 'With an insertion point marker',
items: [
{
title: 'Name entry prompt',
content: '<p><strong>Enter your name:</strong>{{mce-cursor}}</p><p><em>Include both your given and family names, in your preferred order.</em></p>'
},
{
title: 'Letter outline',
content: '<p>{{Current.Date}}</p><p>{{Honorific}} {{Person.Name.Last}},</p><p>{{mce-cursor}} </p><p>Regards,</p><p>{{staff.digital.signature}}</p><p>{{Staff.Name}}</p><p>{{Staff.Email}}</p>'
},
],
},
],
mergetags_list: [
{
value: 'Current.Date',
title: 'Current date in DD/MM/YYYY format'
},
{
value: 'Current.Time',
},
{
value: 'Honorific',
},
{
title: 'Person',
menu: [
{
value: 'Customer.Name.Given',
title: 'customer first name'
},
{
value: 'Customer.Name.Family',
title: 'customer family name'
},
{
value: 'Customer.Name.Full',
title: 'customer full name'
},
{
value: 'Staff.Name.Full',
title: 'staff full name'
},
{
value: 'Staff.Digital.Signature',
title: 'staff digital signaure'
},
{
title: 'Email',
menu: [
{
value: 'Customer.Email'
},
{
value: 'Staff.Email'
}
]
}
]
}
]
});
The mce-clipboard marker
This feature is only available for TinyMCE 6.8 and later. |
The {{mce-clipboard}}
marker is a fixed string for adding to any template.
The string to add is as follows: {{mce-clipboard}}
.
Whenever a user inserts a template containing the {{mce-clipboard}}
marker, the editor will replace those markers with the actual content from the clipboard.
-
TinyMCE
-
HTML
-
JS
-
Edit on CodePen
<textarea id="template-mce-clipboard">
<h3>Using the {{mce-clipboard}} Marker with Templates</h3>
<h4>Before inserting the example template, <strong>type in your name</strong> to the editor, select and copy it to your clipboard by using <strong>Ctrl+C</strong> for Windows users, or <strong>⌘+C</strong> for Mac users</h4>
<div>
<ol>
<li>
Select <strong>Template…</strong> from the <strong>Insert</strong> menu or by selecting the <strong>Insert template</strong> toolbar button.
</li>
<li>
Select a template to add to the TinyMCE document from the <strong>Templates</strong> dialog that presents.
<ol>
<li>
<p>Click the <strong>Without an <code>{{mce-clipboard}}</code> marker</strong> template.</p>
<p>The template should be inserted into the editor content regardless of any clipboard content./p>
</li>
<li>
<p>Click the <strong>With a <code>{{mce-clipboard}}</code> marker</strong> template.</p>
<p><em>When a template <strong>does</strong> contain a valid {{mce-clipboard}} marker, the current content saved in the users clipboard will <strong>replace</strong> the marker when the user inserts the template.</em></p>
</li>
</ol>
</li>
<li>
Click <strong>Insert</strong> or press <strong>Return</strong>.
</li>
</ol>
</div>
</textarea>
tinymce.init({
selector: "textarea#template-mce-clipboard",
plugins: [ "advtemplate", "code", "help"],
toolbar: "undo redo | inserttemplate",
advtemplate_templates: [
{
title: 'Without an mce-clipboard marker',
content: '<p>Hi , Thank you for visiting this page. We truly appreciate and value your feedback and any feature requests you may have While you are here, take a moment to explore mce-cursor, its another powerful tool designed for Templates</p>'
},
{
title: 'With an mce-clipboard marker',
content: '<p>Hi {{mce-clipboard}}, Thank you for visiting this page. We truly appreciate and value your feedback and any feature requests you may have While you are here, take a moment to explore mce-cursor {{mce-clipboard}}, its another powerful tool designed for Templates</p>'
}
],
});
Options
The following configuration options affect the behavior of the Templates plugin.
advtemplate_templates
This option lets you specify a static list of predefined templates that can be inserted using the Templates dialog. It is for scenarios where the provided template list is unchangeable. In this use-case, there is no need to set up a persistent template store and provide a more complex plugin configuration.
Type: Array
The template list assigned to the advtemplate_templates
option must adhere to the following requirements:
-
Each item must have a non-empty
title
value. -
Each template item is required to include a non-empty
content
value. -
Each category item is required to include a
items
sublist, which can be empty. -
Category items must not contain nested subcategories.
Example: using advtemplate_templates
tinymce.init({
selector: 'textarea#advtemplate', // change this value according to your html
plugins: "advtemplate",
toolbar: "inserttemplate",
advtemplate_templates: [
{
title: 'Template 1',
content: 'Template 1 content'
},
{
title: 'Category 2',
items: [
{
title: 'Template 2.1',
content: 'Template 2.1 content'
},
{
title: 'Template 2.2',
content: 'Template 2.2 content'
}
]
}
],
});
advtemplate_list
The plugin uses the advtemplate_list
asynchronous function to retreive the template list.
Type: Function
(Returns a Promise)
Input parameters: None
Return data: Array
Example: using advtemplate_list
tinymce.init({
selector: 'textarea#advtemplate', // change this value according to your html
plugins: ["advtemplate"],
advtemplate_list: () =>
fetch('/categories', {
method: 'GET',
})
.then((response) => response.json())
.then((data) => data)
.catch((error) => console.log('Failed to get template list\n' + error)),
});
The data returned by advtemplate_list
must adhere to the following requirements:
-
Each list item must have a unique
id
value. -
Each list item must have a non-empty
title
value. -
Each category item is required to include an
items
sublist, which can be empty. -
Category items must not contain nested subcategories.
-
Template item is not required to include a
content
value.
advtemplate_get_template
The plugin uses the advtemplate_get_template
asynchronous function to get a template.
Type: Function
(Returns a Promise)
Input parameters:
Field | Type | Required? | Description |
---|---|---|---|
|
|
required |
The id of the template to get. |
Return data:
Field | Type | Description |
---|---|---|
|
|
The id of the template. |
|
|
The title of the template. |
|
|
The content of the template. |
Example: using advtemplate_get_template
tinymce.init({
selector: 'textarea#advtemplate', // change this value according to your html
plugins: ["advtemplate"],
advtemplate_get_template: (id) =>
fetch('/templates/' + id, {
method: 'GET',
})
.then((response) => response.json())
.then(({ id, title, content }) => ({id, title, content}))
.catch((error) => console.log('Failed to get template\n' + error)),
});
advtemplate_create_category
The plugin uses the advtemplate_create_category
asynchronous function to create a category.
Type: Function
(Returns a Promise)
Input parameters:
Field | Type | Required? | Description |
---|---|---|---|
|
|
required |
The title of the category. |
Return data:
Field | Type | Description |
---|---|---|
|
|
The id of the newly created category. |
Example: using advtemplate_create_category
tinymce.init({
selector: 'textarea#advtemplate', // change this value according to your html
plugins: ["advtemplate"],
advtemplate_create_category: (title) =>
fetch('/categories', {
method: 'POST',
body: JSON.stringify({
title
}),
})
.then((response) => response.json())
.then(({ id }) => ({ id }))
.catch((error) => console.log('Failed to create category\n' + error)),
});
advtemplate_create_template
The plugin uses the advtemplate_create_template
asynchronous function to create a template.
Type: Function
(Returns a Promise)
Input parameters:
Field | Type | Required? | Description |
---|---|---|---|
|
|
required |
The title of the template. |
|
|
required |
The content of the template. |
|
|
optional |
The parent category id. |
Return data:
Field | Type | Description |
---|---|---|
|
|
The id of newly created template. |
Example: using advtemplate_create_template
tinymce.init({
selector: 'textarea#advtemplate', // change this value according to your html
plugins: ["advtemplate"],
advtemplate_create_template: (title, content, categoryId) =>
fetch('/templates', {
method: 'POST',
body: JSON.stringify({
title,
content,
categoryId
}),
})
.then((response) => response.json())
.then(({ id }) => ({ id }))
.catch((error) => console.log('Failed to create template\n' + error)),
});
advtemplate_rename_category
The plugin uses the advtemplate_rename_category
asynchronous function to rename a category.
Type: Function
(Returns a Promise)
Input parameters:
Field | Type | Required? | Description |
---|---|---|---|
|
|
required |
The id of the category to rename. |
|
|
required |
New category title. |
Return data:
Empty object {}
Example: using advtemplate_rename_category
tinymce.init({
selector: 'textarea#advtemplate', // change this value according to your html
plugins: ["advtemplate"],
advtemplate_rename_category: (id, title) =>
fetch('/categories/' + id, {
method: 'PUT',
body: JSON.stringify({
title
}),
})
.then(() => ({}))
.catch((error) => console.log('Failed to rename category\n' + error)),
});
advtemplate_rename_template
The plugin uses the advtemplate_rename_template
asynchronous function to rename a template.
Type: Function
(Returns a Promise)
Input parameters:
Field | Type | Required? | Description |
---|---|---|---|
|
|
required |
The id of the template to rename. |
|
|
required |
New template title. |
Return data:
Empty object {}
Example: using advtemplate_rename_template
tinymce.init({
selector: 'textarea#advtemplate', // change this value according to your html
plugins: ["advtemplate"],
advtemplate_rename_template: (id, title) =>
fetch('/templates/' + id, {
method: 'PUT',
body: JSON.stringify({
title
}),
})
.then(() => ({}))
.catch((error) => console.log('Failed to rename template\n' + error)),
});
advtemplate_delete_template
The plugin uses the advtemplate_delete_template
asynchronous function to delete a template.
Type: Function
(Returns a Promise)
Input parameters:
Field | Type | Required? | Description |
---|---|---|---|
|
|
required |
The id of the template to delete. |
Return data:
Empty object {}
Example: using advtemplate_delete_template
tinymce.init({
selector: 'textarea#advtemplate', // change this value according to your html
plugins: ["advtemplate"],
advtemplate_delete_template: (id) =>
fetch('/templates/' + id, {
method: 'DELETE',
})
.then(() => ({}))
.catch((error) => console.log('Failed to delete template\n' + error)),
});
advtemplate_delete_category
The plugin uses the advtemplate_delete_category
asynchronous function to delete a category.
Type: Function
(Returns a Promise)
Input parameters:
Field | Type | Required? | Description |
---|---|---|---|
|
|
required |
The id of the category to delete. |
Return data:
Empty object {}
Example: using advtemplate_delete_category
tinymce.init({
selector: 'textarea#advtemplate', // change this value according to your html
plugins: ["advtemplate"],
advtemplate_delete_category: (id) =>
fetch('/categories/' + id, {
method: 'DELETE',
})
.then(() => ({}))
.catch((error) => console.log('Failed to delete category\n' + error)),
});
advtemplate_move_template
The plugin uses the advtemplate_move_template
asynchronous function to move the template to another category.
Type: Function
(Returns a Promise)
Input parameters:
Field | Type | Required? | Description |
---|---|---|---|
|
|
required |
The id of the template to move . |
|
|
optional |
The id of the destination category. |
Return data:
Empty object {}
Example: using advtemplate_move_template
tinymce.init({
selector: 'textarea#advtemplate', // change this value according to your html
plugins: ["advtemplate"],
advtemplate_move_template: (templateId) =>
fetch('/templates/' + templateId, {
method: 'PATCH',
body: JSON.stringify({
newCategoryId
}),
})
.then(() => ({}))
.catch((error) => console.log('Failed to move template\n' + error)),
});
advtemplate_move_category_items
The plugin uses the advtemplate_move_category_items
asynchronous function to move all templates from a given category to the another one.
Type: Function
(Returns a Promise)
Input parameters:
Field | Type | Required? | Description |
---|---|---|---|
|
|
required |
The id of the source category . |
|
|
optional |
The id of the destination category. |
Return data:
Empty object {}
Example: using advtemplate_move_category_itmes
tinymce.init({
selector: 'textarea#advtemplate', // change this value according to your html
plugins: ["advtemplate"],
advtemplate_move_category_items: (oldCategoryId, newCategoryId) =>
fetch('/categories/' + oldCategoryId, {
method: 'PATCH',
body: JSON.stringify({
newCategoryId
}),
})
.then(() => ({}))
.catch((error) => console.log('Failed to move category items\n' + error)),
});
Toolbar buttons
The Templates plugin provides the following toolbar buttons:
Toolbar button identifier | Description |
---|---|
|
Opens the Templates dialog which presents all templates available to the particular TinyMCE instance for selection and insertion. |
|
Open the New template dialog, allowing for the selected text to be saved as a named template and placed in an already-set category. If there is no selection current in the TinyMCE editor, this button is disabled. |
These toolbar buttons can be added to the editor using:
-
The
toolbar
configuration option. -
The
quickbars_insert_toolbar
configuration option.
Menu items
The Templates plugin provides the following menu items:
Menu item identifier | Default Menu Location | Description |
---|---|---|
|
Insert |
Opens the Templates dialog which presents all templates available to the particular TinyMCE instance for selection and insertion. |
|
Tools |
Open the New template dialog, allowing for the selected text to saved as a named template and placed in an already-set category. If there is no selection current in the TinyMCE editor, this menu item is disabled. |
These menu items can be added to the editor using:
-
The
menu
configuration option. -
The
contextmenu
configuration option.
Commands
The Templates plugin provides the following TinyMCE commands.
Command | Description |
---|---|
AdvTemplateAddDialog |
Opens the |
AdvTemplateInsertDialog |
Opens the |
AdvTemplateInsertTemplateById |
Adds a new template specified by the value of its ID. |
tinymce.activeEditor.execCommand('AdvTemplateAddDialog');
tinymce.activeEditor.execCommand('AdvTemplateInsertDialog');
// Adds a new template, which ID is 122, to the document.
tinymce.activeEditor.execCommand('AdvTemplateInsertTemplateById', false, '122')