Skip to main content
Back to examples
Popular features/Rollup vs preview
Loading live demo…from dhtmlxcode.com
Popular features

Rollup vs preview

Compare native rollup markers on a collapsed workstream's summary bar against split rendering that previews every child task on the same row.

gantt.config.row_height = 40;
gantt.config.bar_height = 26;
gantt.config.scale_height = 50;
gantt.config.min_column_width = 58;
gantt.config.show_links = true;
gantt.config.open_split_tasks = true;
gantt.config.start_date = new Date(2026, 6, 5);
gantt.config.end_date = new Date(2026, 7, 31);

gantt.config.columns = [
	{name: "text", label: "Workstream", tree: true, width: 220, resize: true},
	{name: "start_date", label: "Start", align: "center", width: 100, resize: true},
	{name: "duration", label: "Days", align: "center", width: 62, resize: true},
	{name: "add", width: 40, resize: true}
];

gantt.config.scales = [
	{unit: "month", step: 1, format: "%F, %Y"},
	{unit: "day", step: 2, format: "%j, %D"}
];

gantt.init("gantt_here");

/* ---------------------------------------------------------------------------
 *  MODE SWITCH: "rollup" (native) vs "preview" (custom addTaskLayer)
 * ------------------------------------------------------------------------ */
let MODE = "preview";
/* one flagged deliverable per collapsed workstream: App Build/Content/QA/Launch
   stay open by default, so a rollup flag there would never surface a marker */
let ROLLUP_IDS = [102, 202, 302];
let SPLIT_PARENT_IDS = [100, 200, 300];

let MODE_INFO = {
	rollup: "Native <b>rollup</b> markers &middot; only tasks flagged <code>rollup: true</code> (Market scan, Wireframes, Data model) surface on the collapsed bar &middot; everything else in the workstream stays hidden",
	preview: "Native <b>split-task preview</b> &middot; collapsed workstreams use <code>render: \"split\"</code> to display every child on the parent row"
};

function setMode(mode) {
	MODE = mode;

	SPLIT_PARENT_IDS.forEach(function (id) {
		if (!gantt.isTaskExists(id)) return;

		let task = gantt.getTask(id);
		task.render = mode === "preview" ? "split" : "";
		task.$open = false;
	});

	ROLLUP_IDS.forEach(function (id) {
		if (!gantt.isTaskExists(id)) return;

		gantt.getTask(id).rollup = mode === "rollup";
	});

	DHX.ui.setActiveByAttribute("#mode_seg .dhx_btn", "data-mode", mode, "active");
	gantt.message({id: "mode_info", text: MODE_INFO[mode], expire: -1});

	gantt.render();
}

gantt.templates.grid_row_class = gantt.templates.task_class = function (start, end, task) {
	let css = [];
	if (gantt.isSummaryTask(task)) {
		css.push("task-parent");
	}
	if (MODE === "rollup" && task.rollup && task.type === gantt.config.types.task) {
		css.push("rollup_hl");
	}

	return css.join(" ");
};

/* ---------------------------------------------------------------------------
 *  DATA: identical to 104_subtask_summary_readable.html
 * ------------------------------------------------------------------------ */
gantt.parse({
	tasks: [
		{id: 1, text: "Product Launch Plan", type: "project", open: true, parent: 0, color: "#20b56b"},

		{id: 100, text: "Discovery", type: "project", parent: 1, open: false, color: "#20b56b"},
		{id: 101, text: "Interviews", start_date: "2026-07-06", duration: 4, parent: 100, progress: 1, color: "#4f7df3"},
		{id: 102, text: "Market scan", start_date: "2026-07-11", duration: 4, parent: 100, progress: 1, color: "#4f7df3"},
		{id: 103, text: "Pain points", start_date: "2026-07-16", duration: 4, parent: 100, progress: 0.8, color: "#4f7df3"},
		{id: 104, text: "Decision memo", start_date: "2026-07-21", duration: 3, parent: 100, progress: 0.6, color: "#4f7df3"},

		{id: 200, text: "Experience", type: "project", parent: 1, open: false, color: "#20b56b"},
		{id: 201, text: "Journey map", start_date: "2026-07-13", duration: 4, parent: 200, progress: 1, color: "#7c6ee6"},
		{id: 202, text: "Wireframes", start_date: "2026-07-18", duration: 5, parent: 200, progress: 0.8, color: "#7c6ee6"},
		{id: 203, text: "Prototype", start_date: "2026-07-24", duration: 5, parent: 200, progress: 0.5, color: "#7c6ee6"},
		{id: 204, text: "Usability", start_date: "2026-07-30", duration: 4, parent: 200, progress: 0.3, color: "#7c6ee6"},

		{id: 300, text: "Architecture", type: "project", parent: 1, open: false, color: "#20b56b"},
		{id: 301, text: "API shape", start_date: "2026-07-20", duration: 4, parent: 300, progress: 1, color: "#0f9f9a"},
		{id: 302, text: "Data model", start_date: "2026-07-25", duration: 5, parent: 300, progress: 0.7, color: "#0f9f9a"},
		{id: 303, text: "Auth flow", start_date: "2026-07-31", duration: 4, parent: 300, progress: 0.5, color: "#0f9f9a"},
		{id: 304, text: "Review", start_date: "2026-08-05", duration: 3, parent: 300, progress: 0.2, color: "#0f9f9a"},

		{id: 400, text: "App Build", type: "project", parent: 1, open: true, color: "#20b56b"},
		{id: 401, text: "Shell", start_date: "2026-07-27", duration: 5, parent: 400, progress: 0.7, color: "#4f7df3"},
		{id: 402, text: "Dashboard", start_date: "2026-08-03", duration: 6, parent: 400, progress: 0.5, color: "#4f7df3"},
		{id: 403, text: "Settings", start_date: "2026-08-10", duration: 5, parent: 400, progress: 0.3, color: "#4f7df3"},
		{id: 404, text: "Billing", start_date: "2026-08-15", duration: 4, parent: 400, progress: 0.2, color: "#4f7df3"},
		{id: 405, text: "Notifications", start_date: "2026-08-19", duration: 4, parent: 400, progress: 0.1, color: "#4f7df3"},

		{id: 500, text: "Content", type: "project", parent: 1, open: true, color: "#20b56b"},
		{id: 501, text: "Help topics", start_date: "2026-08-03", duration: 4, parent: 500, progress: 0.5, color: "#d78a24"},
		{id: 502, text: "Onboarding", start_date: "2026-08-08", duration: 5, parent: 500, progress: 0.4, color: "#d78a24"},
		{id: 503, text: "Release notes", start_date: "2026-08-14", duration: 4, parent: 500, progress: 0.2, color: "#d78a24"},
		{id: 504, text: "Email copy", start_date: "2026-08-19", duration: 3, parent: 500, progress: 0.1, color: "#d78a24"},
		{id: 505, text: "Localization", start_date: "2026-08-22", duration: 3, parent: 500, progress: 0, color: "#d78a24"},

		{id: 600, text: "QA", type: "project", parent: 1, open: true, color: "#20b56b"},
		{id: 601, text: "Regression", start_date: "2026-08-10", duration: 5, parent: 600, progress: 0.3, color: "#4f7df3"},
		{id: 602, text: "Security", start_date: "2026-08-16", duration: 4, parent: 600, progress: 0.2, color: "#4f7df3"},
		{id: 603, text: "Load test", start_date: "2026-08-21", duration: 4, parent: 600, progress: 0, color: "#4f7df3"},
		{id: 604, text: "Bug bash", start_date: "2026-08-26", duration: 3, parent: 600, progress: 0, color: "#4f7df3"},
		{id: 605, text: "Accessibility audit", start_date: "2026-08-29", duration: 1, parent: 600, progress: 0, color: "#4f7df3"},

		{id: 700, text: "Launch", type: "project", parent: 1, open: true, color: "#20b56b"},
		{id: 701, text: "Runbook", start_date: "2026-08-17", duration: 3, parent: 700, progress: 0.2, color: "#7c6ee6"},
		{id: 702, text: "Support prep", start_date: "2026-08-20", duration: 4, parent: 700, progress: 0.1, color: "#7c6ee6"},
		{id: 703, text: "Dry run", start_date: "2026-08-25", duration: 2, parent: 700, progress: 0, color: "#7c6ee6"},
		{id: 704, text: "Go-live", start_date: "2026-08-28", type: "milestone", parent: 700, progress: 0, duration: 0, color: "#c765dd"}
	],
	links: [
		{id: 1, source: 101, target: 102, type: "0"},
		{id: 2, source: 102, target: 103, type: "0"},
		{id: 3, source: 103, target: 104, type: "0"},

		{id: 4, source: 201, target: 202, type: "0"},
		{id: 5, source: 202, target: 203, type: "0"},
		{id: 6, source: 203, target: 204, type: "0"},

		{id: 7, source: 301, target: 302, type: "0"},
		{id: 8, source: 302, target: 303, type: "0"},
		{id: 9, source: 303, target: 304, type: "0"},

		{id: 10, source: 401, target: 402, type: "0"},
		{id: 11, source: 402, target: 403, type: "0"},
		{id: 12, source: 403, target: 404, type: "0"},
		{id: 22, source: 404, target: 405, type: "0"},

		{id: 13, source: 501, target: 502, type: "0"},
		{id: 14, source: 502, target: 503, type: "0"},
		{id: 15, source: 503, target: 504, type: "0"},
		{id: 23, source: 504, target: 505, type: "0"},

		{id: 16, source: 601, target: 602, type: "0"},
		{id: 17, source: 602, target: 603, type: "0"},
		{id: 18, source: 603, target: 604, type: "0"},
		{id: 24, source: 604, target: 605, type: "0"},

		{id: 19, source: 701, target: 702, type: "0"},
		{id: 20, source: 702, target: 703, type: "0"},
		{id: 21, source: 703, target: 704, type: "0"}
	]
});

setMode("preview");
<!DOCTYPE html>
<html lang="en">
<head>
	<meta http-equiv="Content-type" content="text/html; charset=utf-8">
	<title>Rollup markers vs. full subtask preview: dhtmlxGantt</title>
	<script src="../../codebase/dhtmlxgantt.js"></script>
	<link rel="stylesheet" href="../../codebase/dhtmlxgantt.css">
	<link rel="stylesheet" href="../common/demo-controls/dhx_controls.css">
	<script src="../common/demo-controls/dhx_controls.js"></script>
	<style>
		body { display: flex; flex-direction: column; }
		#gantt_here { flex: 1 1 auto; min-height: 0; width: 100%; }

		.gantt_task_line {
			border: none;
			border-radius: 6px;
		}

		.gantt_task_line.gantt_project {
			border-radius: 4px;
		}

		.gantt_row.task-parent .gantt_tree_content {
			font-weight: 700;
		}

		.gantt_task_line.rollup_hl {
			background: #4f7df3;
			box-shadow: 0 1px 4px rgba(79,125,243,.45);
		}
		.gantt_task_line.rollup_hl .gantt_task_progress { background: rgba(255,255,255,.35); }
		.gantt_task_line.gantt_rollup_child { background: #4f7df3; border-radius: 6px; box-shadow: 0 1px 3px rgba(16,24,40,.35); opacity: .95; }
		.gantt_task_line.gantt_rollup_child.gantt_milestone { background: #d97706; }
	</style>
</head>
<body>

<div class="dhx_header" style="position:relative; justify-content:center; gap:14px">
	<span class="dhx_demo_hint" style="position:absolute; left:14px; top:50%; transform:translateY(-50%)">Discovery, Experience &amp; Architecture stay collapsed</span>
	<div class="dhx_seg" id="mode_seg">
		<button class="dhx_btn" data-mode="rollup" onclick="setMode('rollup')">Key rollups</button>
		<button class="dhx_btn active" data-mode="preview" onclick="setMode('preview')">Full preview</button>
	</div>
</div>

<div id="gantt_here"></div>


</body>
</html>