DHTMLX RichText. Using RichText as an editor for Scheduler example
Live example
RichText can serve as the editor inside another component. This demo embeds it in a DHTMLX Scheduler event form, so opening an event turns its details field into an editor with formatting, lists, and links. Saving the form writes the formatted content back onto the event.
const toolbar = [
"bold",
"italic",
"underline",
"separator",
"link",
"separator",
"fullscreen",
"bulleted-list",
"numbered-list"
];
let rtext = null;
scheduler.form_blocks["custom_editor"] = {
render: function (sns) {
return `<div style="height:300px;width:100%" id="richtext_container"></div>`;
},
set_value: function (node, value, ev) {
if (rtext) {
rtext.destructor();
rtext = null;
}
rtext = new richtext.Richtext("#richtext_container", {
value: value ?? "default text details",
toolbar
});
},
get_value: function (node, ev) {
return rtext.getValue();
},
focus: function (node) {
}
};
scheduler.plugins({
tooltip: true
});
scheduler.config.header = [
"day",
"week",
"month",
"date",
"prev",
"today",
"next"
];
scheduler.config.wide_form = true;
scheduler.keys.edit_save = -1; // prevent closing lightbox with enter
scheduler.config.lightbox.sections = [
{ name: "Details", map_to: "details", type: "custom_editor", focus: true },
{ name: "time", height: 72, type: "time", map_to: "auto" }
];
// template for event text
scheduler.templates.event_text = function (start, end, event) {
return `${event.text}<br>
${event.details}`
}
// template for tooltips
scheduler.templates.tooltip_text = function(start,end,event){
return event.details
};
// destroy richtext editor
scheduler.attachEvent("onAfterLightbox", function () {
if (rtext) {
rtext.destructor();
rtext = null;
}
});
scheduler.init('scheduler_here', new Date(2022, 3, 20), "week");
scheduler.parse([
{ start_date: "2022-04-18 09:00", end_date: "2022-04-18 19:00", text: "Customer Service, Tax Filing, Design", "details": `<ol><li><span style="font-weight:bold;">Customer Service and Lead Generation</span></li><li><span style="font-weight:bold;">Tax Preparation and Filing</span><ul><li>Social Media Monitoring and Reputation Management</li></ul></li><li><span style="font-weight:bold;">Creative and Design Work</span><ul><li>Product Design and Prototyping</li><li>Animation and Motion Graphics</li></ul></li><li><span style="font-weight:bold;">Patent and Intellectual Property Management</span></li></ol>` },
{ start_date: "2022-04-20 10:00", end_date: "2022-04-21 16:00", text: "IT Support, Software, Website", "details": `<ol><li><span style="font-weight:bold;">IT Support and Helpdesk Services</span><ul><li>Technical Support for End Users</li></ul></li><li><span style="font-weight:bold;">Software Development and Maintenance</span><ul><li>Training and E-Learning Content Development</li></ul></li><li><span style="font-weight:bold;">Website Development and Management</span></li></ol>` },
{ start_date: "2022-04-21 06:00", end_date: "2022-04-21 19:00", text: "HR, SEO, Content", "details": `<ol><li><span style="font-weight:bold;">Human Resources and Recruitment Assistance</span><ul><li>Patent and Intellectual Property Management</li></ul></li><li><span style="font-weight:bold;">Search Engine Optimization (SEO) Services</span><ul><li>Business Intelligence and Data Analytics</li></ul></li><li><span style="font-weight:bold;">Content Writing and Copywriting</span></li></ol>` },
{ start_date: "2022-04-23 16:00", end_date: "2022-04-23 17:00", text: "Data Entry, Translation, Design", "details": `<ol><li><span style="font-weight:bold;">Data Entry and Database Management</span><ul><li>Legal Advisory and Contract Management</li><li>Environmental Compliance and Sustainability Services</li><li>Event Marketing and Promotions</li></ul></li><li><span style="font-weight:bold;">Translation and Localization Services</span></li><li><span style="font-weight:bold;">Creative and Design Work</span></li></ol>` },
{ start_date: "2022-04-22 09:00", end_date: "2022-04-22 18:00", text: "Market Research, Tax, Quality", "details": `<ol><li><span style="font-weight:bold;">Market Research and Analysis</span></li><li><span style="font-weight:bold;">Tax Preparation and Filing</span><ul><li>Public Relations and Media Outreach</li></ul></li><li><span style="font-weight:bold;">Quality Assurance and Testing</span></li></ol>` }
]);
<div id="scheduler_here" class="dhx_cal_container" style='width:100%; height:100%;'></div>
<style>
body,
html {
width: 100%;
height: 100%;
margin: unset;
}
#richtext_container {
--wx-background-alt: #FFFFFF;
}
ol,
ul {
padding: 0 15px;
margin: 0;
}
.dhx_wrap_section:has(#richtext_container) .dhx_cal_lsection {
width: 0;
padding: 0;
}
.wx-editor-wrapper {
border-bottom: var(--wx-border);
}
.dhx_cal_lcontrols .dhx_btn_set.dhx_delete_btn_set,
.dhx_delete_btn_set:hover {
padding: 2px 6px;
border: 1px solid var(--dhx-scheduler-base-colors-error)
}
</style>Use case
Use it when an event needs more than a one-line note, like a calendar where each entry carries a formatted agenda, a checklist, or links. Scheduler handles the calendar and the event form, and RichText handles the formatted details inside it. The two connect through a custom Scheduler lightbox section that mounts the editor and reads its value on save. To make it yours, create the editor in the section's set_value with your toolbar, and return rtext.getValue() from get_value.
How to do this in your app
- Register a custom lightbox section: define
scheduler.form_blocks["custom_editor"]withrender,set_value,get_value, andfocus, then list it inscheduler.config.lightbox.sections. - Mount the editor on open: in
set_value, callnew richtext.Richtext("#richtext_container", { value, toolbar })so the form shows the event's saved details. - Save the content back: in
get_value, returnrtext.getValue(). Scheduler stores that value in the event's mapped field (details). - Trim the toolbar: pass a short
toolbararray (bold, italic, underline, link, lists, fullscreen) to fit the compact form.
Good to know
- Destroy the editor before reusing the container: the demo calls
rtext.destructor()and clears the reference before creating a new instance and after the lightbox closes, so each open starts clean. - Preserve intentionally empty content: use
value ?? "default text details"so the fallback applies only when the mapped value is missing, not when it is an empty string. get_valuereads live from the editor: it callsgetValue()at save time, so the returned HTML reflects the latest edits.- The details field is mapped: the section's
map_to: "details"links the editor to the event'sdetailsproperty, which also feeds the event and tooltip templates.
API reference
- getValue method: Returns the editor content to save on the event
- toolbar config: Defines the compact toolbar for the form
- DHTMLX Scheduler lightbox: Custom sections and editors in the Scheduler event form
Related examples
- Editor inside Gantt: the editor inside a Gantt task form
- Full toolbar: every built-in control listed in one array
- Insert text at cursor: content dropped in at the caret from your own buttons