DHTMLX RichText. Using RichText as an editor for Gantt example
Live example
RichText can serve as the editor inside another component. This demo embeds it in a DHTMLX Gantt task form: opening a task turns its details field into an editor with formatting, lists, and links, and saving writes the content back onto the task.
const toolbar = [
"bold",
"italic",
"underline",
"separator",
"link",
"separator",
"fullscreen",
"bulleted-list",
"numbered-list"
];
let rtext = null;
gantt.form_blocks["custom_editor"] = {
render: function (sns) {
return `<div style="height:350px;width:100%" id="richtext_container"></div>`;
},
set_value: function (node, value, task) {
if (rtext) {
rtext.destructor();
rtext = null;
}
rtext = new richtext.Richtext("#richtext_container", {
value: value ?? "default text details",
toolbar
});
},
get_value: function (node, task) {
return rtext.getValue();
},
focus: function (node) {
}
};
gantt.plugins({
tooltip: true
});
gantt.config.wide_form = true;
gantt.keys.edit_save = -1; // prevent closing lightbox with enter
gantt.config.lightbox.sections = gantt.config.lightbox.project_sections = [
{ name: "Details", map_to: "details", type: "custom_editor", focus: true },
{ name: "time", type: "duration", map_to: "auto" }
];
// template for tooltips
gantt.templates.tooltip_text = function(start,end,task){
return task.details
};
// destroy richtext editor
gantt.attachEvent("onAfterLightbox", function () {
if (rtext) {
rtext.destructor();
rtext = null;
}
});
const data = {
tasks: [
{ id: "10", text: "Project #1", start_date: "01-04-2025", duration: 3, progress: 0.4, open: true, 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>` },
{ id: "1", text: "Task #1", start_date: "02-04-2025", duration: 2, progress: 0.6, parent: "10", 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>` },
{ id: "2", text: "Task #2", start_date: "01-04-2025", duration: 2, progress: 0.6, parent: "10", 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>` },
{ id: "20", text: "Project #2", start_date: "01-04-2025", duration: 3, progress: 0.4, type: "project", open: true, 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>` },
{ id: "3", text: "Task #3", start_date: "02-04-2025", duration: 2, progress: 0.6, parent: "20", 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>` },
{ id: "4", text: "Task #4", start_date: "01-04-2025", duration: 2, progress: 0.6, parent: "20", 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>` },
],
links: [
{ id: 1, source: 1, target: 2, type: "0" },
{ id: 2, source: 2, target: 3, type: "0" },
{ id: 3, source: 3, target: 4, type: "0" },
]
}
gantt.init("gantt_here");
gantt.parse(data);
<div id="gantt_here" style="width:100%; height:100%;"></div>
<style>
body,
html {
width: 100%;
height: 100%;
margin: unset;
}
#richtext_container {
--wx-background-alt: #FFFFFF;
}
.gantt_wrap_section:has(#richtext_container) .gantt_cal_lsection {
width: 0;
padding: 0;
}
.wx-editor-wrapper {
border-bottom: var(--wx-border);
}
.gantt_cal_lcontrols .gantt_btn_set.gantt_delete_btn_set,
.gantt_delete_btn_set:hover {
padding: 2px 6px;
border: 1px solid var(--dhx-gantt-base-colors-error)
}
</style>Use case
Use it when a task needs more than a plain-text note, like a project plan where each task carries a formatted brief, a checklist, or links to specs. Gantt handles the schedule and the task form, and RichText handles the formatted details inside it. The two connect through a custom Gantt 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
gantt.form_blocks["custom_editor"]withrender,set_value,get_value, andfocus, then list it ingantt.config.lightbox.sections. - Mount the editor on open: in
set_value, callnew richtext.Richtext("#richtext_container", { value, toolbar })so the form shows the task's saved details. - Save the content back: in
get_value, returnrtext.getValue(). Gantt stores that value in the task'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, not hardcoded: the section's
map_to: "details"links the editor to the task'sdetailsproperty, which also feeds the tooltip template.
API reference
- getValue method: Returns the editor content to save on the task
- toolbar config: Defines the compact toolbar for the form
- DHTMLX Gantt form blocks: Defines custom controls in the Gantt task form
Related examples
- Editor inside Scheduler: the editor inside a Scheduler event form
- Full toolbar: every built-in control listed in one array
- Markdown and HTML: content read and written as HTML, Markdown, or plain text