TL;DR: Need dynamic placeholders in your React editor? This guide dives into adding merge fields in React Rich Text Editor to streamline automated content generation. You’ll learn how to integrate the Rich Text editor in a Vite-based React app, configure a custom toolbar for inserting merge fields, and apply techniques to replace those fields with live data at runtime. Perfect for developers building document templates, email editors, or CRM systems where dynamic content is essential.
Merge fields are a powerful feature in modern Rich Text Editors, enabling dynamic content creation and personalized experiences in documents, emails, and forms. The Syncfusion React Rich Text Editor, a WYSIWYG editor, supports merge fields. This blog explains how to use merge fields in a React app and their benefits.
What are merge fields?
Merge fields are placeholders embedded in content that get dynamically replaced with actual data at runtime. For instance, a field like {{FirstName}} can be replaced with Alex to personalize a greeting. These fields function like variables, enabling you to create adaptable templates that utilize user data, database records, or external inputs.
Use merge fields in Syncfusion React Rich Text Editor
The Syncfusion React Rich Text Editor is a flexible tool for creating and editing rich HTML content. To add merge fields, simply use the executeCommand method with insertHtml. This lets you insert placeholders as custom HTML elements, which you can later replace with dynamic data, perfect for building personalized templates.
Step 1: Set up the React Rich Text Editor
Begin by creating a new React application using Vite. Follow the official Vite setup guide to initialize your project.
Once your project is ready, install the necessary Syncfusion packages for the Rich Text Editor and DropDownButton components by running:
npm install @syncfusion/ej2-react-richtexteditor @syncfusion/ej2-react-splitbuttons --save
To ensure your Rich Text Editor looks great, you’ll need to import the necessary Syncfusion styles. Here’s how you can do it in your App.css file:
@import '../node_modules/@syncfusion/ej2-base/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-icons/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-buttons/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-inputs/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-lists/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-navigations/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-popups/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-richtexteditor/styles/tailwind3.css';
Now, initialize the Rich Text Editor in your App.js file. Import the necessary modules and inject the required services:
import { HtmlEditor, Table, PasteCleanup, Image, Inject, Link, QuickToolbar, RichTextEditorComponent, Toolbar } from '@syncfusion/ej2-react-richtexteditor';
import './App.css';
function App() {
return (
<RichTextEditorComponent>
<p>Welcome to the Syncfusion React Rich Text Editor!</p>
<Inject services={[HtmlEditor, Toolbar, Image, Link, QuickToolbar, Table, PasteCleanup]} />
</RichTextEditorComponent>
);
}
export default App;
Step 2: Insert merge fields
To let users to insert merge fields like {{FirstName}}, use the executeCommand(‘insertHtml’) method. These fields should be styled and made non-editable using <span> elements with the e-mention-chip class.
Next, add a DropDownButton to the toolbar so users can pick from predefined fields. When a field is selected, the select event inserts the placeholder into the editor. Use useRef to manage the editor instance easily.
Refer to the code example below:
import { HtmlEditor, Table, PasteCleanup, Image, Inject, Link, QuickToolbar, RichTextEditorComponent, Toolbar } from '@syncfusion/ej2-react-richtexteditor';
import { DropDownButtonComponent } from '@syncfusion/ej2-react-splitbuttons';
import { useRef } from 'react';
import './App.css';
function App() {
const rteObj = useRef(null);
const valueContent = ` <p>Dear <span class="e-mention-chip">{{FirstName}}</span> <span class="e-mention-chip">{{LastName}}</span>,</p>
<p>Your promotional code is: <span class="e-mention-chip">{{PromoCode}}</span>.</p> `;
const onItemSelect = (args) => {
if (args.item.text && rteObj.current) {
const value = args.item.text.replace(/\s/g, '');
rteObj.current.executeCommand('insertHTML', `<span contenteditable="false" class="e-mention-chip"><span>{{${value}}}</span></span> `,
{ undo: true }
);
rteObj.current.focusIn();
}
};
const toolbarSettings = {
items: [
'Bold', 'Italic', 'Underline', '|', 'Formats', 'Alignments', 'Blockquote', 'OrderedList', 'UnorderedList', '|', 'CreateLink', 'Image', '|', { tooltipText: 'Insert Field', template: '#insertField', command: 'Custom' }, '|', 'SourceCode', 'Undo', 'Redo'
]
};
const data = [
{ text: 'First Name', value: 'FirstName' },
{ text: 'Last Name', value: 'LastName' },
{ text: 'Promo Code', value: 'PromoCode' }
];
return (
<div className="control-wrapper">
<DropDownButtonComponent
id="insertField"
cssClass='e-rte-dropdown-menu'
items={data}
content=
'<span style="display: inline-flex;">
<span class="e-rte-dropdown-btn-text">Insert Field</span>
</span>'
select={onItemSelect}
className="e-rte-dropdown-btn"
/>
<RichTextEditorComponent ref={rteObj} value={valueContent} toolbarSettings={toolbarSettings}>
<Inject services={[HtmlEditor, Toolbar, Image, Link, QuickToolbar, Table, PasteCleanup]} />
</RichTextEditorComponent>
</div>
);
}
export default App;
Now that you’ve inserted merge fields into your content, the next step is to make them functional by replacing these placeholders with actual data. This ensures your content is personalized and ready for real-world use.
Step 3: Replace merge fields with dynamic data
To populate merge fields with actual values:
- Retrieve the editor’s content using getHtml.
- Replace placeholders with real data.
- Update the editor using the value property.
Finally, you can use a Merge Data button to trigger this process. It runs a simple function that maps placeholders to their corresponding values.
Refer to the code example below for implementation details.
import { HtmlEditor, Table, PasteCleanup, Image, Inject, Link, QuickToolbar, RichTextEditorComponent, Toolbar } from '@syncfusion/ej2-react-richtexteditor';
import { DropDownButtonComponent } from '@syncfusion/ej2-react-splitbuttons';
import { useRef } from 'react';
import './App.css';
function App() {
const rteObj = useRef(null);
const valueContent = ` <p>Dear <span class="e-mention-chip">{{FirstName}}</span> <span class="e-mention-chip">{{LastName}}</span>,</p>
<p>Your promotional code is: <span class="e-mention-chip">{{PromoCode}}</span>.</p>`;
const onItemSelect = (args) => {
if (args.item.text && rteObj.current) {
const value = args.item.text.replace(/\s/g, '');
rteObj.current.executeCommand('insertHTML', `<span contenteditable="false" class="e-mention-chip"><span>{{${value}}}</span></span> `,
{ undo: true }
);
rteObj.current.focusIn();
}
};
const onMergeData = () => {
if (rteObj.current) {
let content = rteObj.current.getHtml();
const placeholderData = {
FirstName: 'Alex',
LastName: 'Carter',
PromoCode: 'XYZ789'
};
content = replacePlaceholders(content, placeholderData);
if (rteObj.current.formatter.getUndoRedoStack().length === 0) {
rteObj.current.formatter.saveData();
}
rteObj.current.value = content;
rteObj.current.formatter.saveData();
}
};
const replacePlaceholders = (template, data) => {
return template.replace(/{{(\w+)}}/g, (match, key) => data[key] || match);
};
const toolbarSettings = {
items: [
'Bold', 'Italic', 'Underline', '|', 'Formats', 'Alignments', 'Blockquote',
'OrderedList', 'UnorderedList', '|', 'CreateLink', 'Image', '|',
{ tooltipText: 'Merge Data', template: '#merge_data', command: 'Custom' },
{ tooltipText: 'Insert Field', template: '#insertField', command: 'Custom' },
'|', 'SourceCode', 'Undo', 'Redo'
]
};
const data = [
{ text: 'First Name', value: 'FirstName' },
{ text: 'Last Name', value: 'LastName' },
{ text: 'Promo Code', value: 'PromoCode' }
];
return (
<div className="control-wrapper">
<button
className="e-control e-lib e-btn e-formats-tbar-btn e-rte-elements e-tbar-btn"
tabIndex={-1}
id="merge_data"
style={{ width: '100%' }}
onClick={onMergeData}
>
<span style={{ display: 'inline-flex' }}>
<span className="e-tbar-btn-text">Merge Data</span>
</span>
</button>
<DropDownButtonComponent
id="insertField"
cssClass='e-rte-dropdown-menu'
items={data}
content='<span style="display: inline-flex;"><span class="e-rte-dropdown-btn-text">Insert Field</span></span>'
select={onItemSelect}
className="e-rte-dropdown-btn"
/>
<RichTextEditorComponent ref={rteObj} value={valueContent} toolbarSettings={toolbarSettings}>
<Inject services={[HtmlEditor, Toolbar, Image, Link, QuickToolbar, Table, PasteCleanup]} />
</RichTextEditorComponent>
</div>
);
}
export default App;

Benefits of using merge fields
Merge fields offer more than just dynamic placeholders, they bring efficiency, personalization, and automation to your content workflows. Here are some key advantages:
- Personalized content: Tailor emails, documents, and reports to individual users for better engagement.
- Improved productivity: Automate repetitive tasks like email drafting or document generation.
- Reduced errors: Minimize manual mistakes by automating content population.
- User-friendly interface: The WYSIWYG editor makes it easy to insert and visualize merge fields, no coding required.
- Seamless React integration: The executeCommand method works natively with React, fitting perfectly into component-based architectures.
- Cross-device compatibility: The editor works smoothly across desktops, tablets, and smartphones.
Use cases for merge fields
Merge fields aren’t just useful in theory, they solve real-world problems across various industries. Here are some practical scenarios where they can make a big impact:
- Email campaigns: Personalize bulk emails with names, order details, or offers.
- Document automation: Generate contracts, invoices, or letters with dynamic fields.
- Support systems: Automate responses with ticket IDs and customer details.
- Dynamic web content: Insert personalized data into blogs or CMS platforms
Conclusion
Thank you for taking the time to read our blog post. In this guide, we explored how to enhance automated content generation by integrating merge fields into the Syncfusion React Rich Text Editor within a Vite-based React application. From setting up the editor and customizing the toolbar to inserting and replacing merge fields with dynamic data, you now have the tools to create personalized, real-time content with ease.
To explore more, check out Syncfusion’s online demos and documentation. If you’re an existing Syncfusion user, you can download the setup from the license and downloads page. New users can start with a free 30-day trial.
If you have any questions or feedback, feel free to reach out through the support forum, support portal, or feedback portal. We’re always happy to help!
Related Blogs
- Introducing Emoji Icons Support in the React Rich Text Editor
- Easily Integrate the React Image Editor into the Rich Text Editor
- How to Integrate Syncfusion React Mention Component with Rich Text Editor
- How to Use Syncfusion’s React Rich Text Editor with React Redux Form
This article was originally published at Syncfusion.com.
Top comments (0)