Troubleshooting
Source code
TypeScript ts
// src/components/gantt/GanttBasic.ts
import { defineCustomElements } from '@revolist/revogrid/loader';
defineCustomElements();
import { GanttPlugin, createDefaultTaskTableColumn, defineGanttToolbar } from '@revolist/revogrid-enterprise';
import { currentTheme } from '../composables/useRandomData';
import { calendars, dependencies, ganttConfig, tasks, taskTableColumnProps, toolbarColumns } from './gantt-basic-data';
import './gantt-basic.css';
const { isDark } = currentTheme();
const columns = taskTableColumnProps.map((prop) => createDefaultTaskTableColumn(prop));
export function load(parentSelector: string) {
const parent = document.querySelector(parentSelector);
if (!parent) {
return () => {};
}
const root = document.createElement('section');
const toolbar = document.createElement('div');
const grid = document.createElement('revo-grid');
root.className = 'gantt-basic-demo';
toolbar.className = 'gantt-basic-toolbar';
grid.className = 'gantt-basic-grid';
grid.theme = isDark() ? 'darkCompact' : 'compact';
grid.hideAttribution = true;
grid.plugins = [GanttPlugin];
grid.gantt = ganttConfig;
grid.ganttCalendars = calendars;
grid.ganttDependencies = dependencies;
grid.columns = columns;
root.appendChild(toolbar);
root.appendChild(grid);
parent.appendChild(root);
defineGanttToolbar(toolbar, {
grid,
columns: toolbarColumns,
controls: {
export: false,
baseline: false,
},
});
grid.source = tasks.map((task) => ({ ...task }));
return () => root.remove();
}
Data ts
import type {
CalendarEntity,
DependencyEntity,
GanttToolbarColumnOption,
TaskEntity,
TaskTableColumnProp,
} from '@revolist/revogrid-enterprise';
export const PROJECT_ID = 'project-web-redesign';
export const CALENDAR_ID = 'cal-standard';
export const ganttConfig = {
id: PROJECT_ID,
name: 'Website Redesign',
version: '1',
currency: 'USD',
timeZone: 'UTC',
primaryCalendarId: CALENDAR_ID,
updatedAt: '2026-04-06T00:00:00Z',
zoomPreset: 'week' as const,
allowTaskCreate: true,
};
export const taskTableColumnProps: TaskTableColumnProp[] = [
'wbs',
'name',
'cost',
'startDate',
'endDate',
'duration',
'workHours',
'remainingDurationDays',
'actualStartDate',
'actualFinishDate',
'effortMode',
'effortDriven',
'inactive',
'priority',
'canLevel',
'levelingDelayDays',
'earlyStartDate',
'earlyFinishDate',
'lateStartDate',
'lateFinishDate',
'totalSlackDays',
'startVarianceDays',
'finishVarianceDays',
'durationVarianceDays',
'progressVariancePercent',
'taskMode',
'scheduleOrigin',
'constraintType',
'constraintDate',
'deadlineDate',
'schedulingWarning',
'percentDone',
'predecessors',
'successors',
'status',
'assignees',
'resourceRole',
'resourceCapacity',
'resourceLoadSummary',
];
const initiallyVisibleColumnProps = new Set<TaskTableColumnProp>(['wbs', 'name']);
const allToolbarColumns = [
{ prop: 'actualFinishDate', label: 'Actual Finish' },
{ prop: 'actualStartDate', label: 'Actual Start' },
{ prop: 'assignees', label: 'Assignees' },
{ prop: 'resourceCapacity', label: 'Capacity' },
{ prop: 'canLevel', label: 'Can Level' },
{ prop: 'constraintType', label: 'Constraint' },
{ prop: 'constraintDate', label: 'Constraint Date' },
{ prop: 'cost', label: 'Cost' },
{ prop: 'deadlineDate', label: 'Deadline' },
{ prop: 'duration', label: 'Duration' },
{ prop: 'durationVarianceDays', label: 'Duration Variance' },
{ prop: 'earlyFinishDate', label: 'Early Finish' },
{ prop: 'earlyStartDate', label: 'Early Start' },
{ prop: 'effortDriven', label: 'Effort Driven' },
{ prop: 'effortMode', label: 'Effort Mode' },
{ prop: 'endDate', label: 'End Date' },
{ prop: 'finishVarianceDays', label: 'Finish Variance' },
{ prop: 'inactive', label: 'Inactive' },
{ prop: 'lateFinishDate', label: 'Late Finish' },
{ prop: 'lateStartDate', label: 'Late Start' },
{ prop: 'levelingDelayDays', label: 'Level Delay' },
{ prop: 'resourceLoadSummary', label: 'Load' },
{ prop: 'percentDone', label: '% Done' },
{ prop: 'predecessors', label: 'Predecessors' },
{ prop: 'priority', label: 'Priority' },
{ prop: 'progressVariancePercent', label: 'Progress Variance' },
{ prop: 'remainingDurationDays', label: 'Remaining' },
{ prop: 'resourceRole', label: 'Role' },
{ prop: 'scheduleOrigin', label: 'Scheduled By' },
{ prop: 'schedulingWarning', label: 'Scheduling Warning' },
{ prop: 'startDate', label: 'Start Date' },
{ prop: 'startVarianceDays', label: 'Start Variance' },
{ prop: 'status', label: 'Status' },
{ prop: 'successors', label: 'Successors' },
{ prop: 'name', label: 'Task' },
{ prop: 'taskMode', label: 'Task Mode' },
{ prop: 'totalSlackDays', label: 'Total Slack' },
{ prop: 'wbs', label: 'WBS' },
{ prop: 'workHours', label: 'Work Hours' },
] satisfies Array<Omit<GanttToolbarColumnOption, 'visible'>>;
export const toolbarColumns: GanttToolbarColumnOption[] = [...allToolbarColumns]
.sort((a, b) => a.label.localeCompare(b.label, undefined, { sensitivity: 'base' }))
.map((column) => ({
...column,
visible: initiallyVisibleColumnProps.has(column.prop as TaskTableColumnProp),
}));
export const calendars: CalendarEntity[] = [
{
id: CALENDAR_ID,
name: 'Standard',
timeZone: 'UTC',
workingDays: [1, 2, 3, 4, 5],
holidays: [],
hoursPerDay: 8,
},
];
export const tasks: TaskEntity[] = [
{
id: 't1', projectId: PROJECT_ID, parentId: null,
wbsCode: '1', name: 'Discovery', type: 'summary',
status: 'done',
startDate: '2026-04-06', endDate: '2026-04-17', durationDays: 10,
progressPercent: 100, calendarId: CALENDAR_ID, isCritical: false, tags: [],
},
{
id: 't2', projectId: PROJECT_ID, parentId: 't1',
wbsCode: '1.1', name: 'Stakeholder Interviews', type: 'task',
status: 'done',
startDate: '2026-04-06', endDate: '2026-04-08', durationDays: 3,
progressPercent: 100, calendarId: CALENDAR_ID, isCritical: false, tags: [],
},
{
id: 't3', projectId: PROJECT_ID, parentId: 't1',
wbsCode: '1.2', name: 'Analytics Review', type: 'task',
status: 'done',
startDate: '2026-04-07', endDate: '2026-04-10', durationDays: 4,
progressPercent: 100, calendarId: CALENDAR_ID, isCritical: false, tags: [],
},
{
id: 't4', projectId: PROJECT_ID, parentId: 't1',
wbsCode: '1.3', name: 'Content Inventory', type: 'task',
status: 'done',
startDate: '2026-04-09', endDate: '2026-04-14', durationDays: 4,
progressPercent: 100, calendarId: CALENDAR_ID, isCritical: false, tags: [],
},
{
id: 't5', projectId: PROJECT_ID, parentId: 't1',
wbsCode: '1.4', name: 'Requirements Workshop', type: 'task',
status: 'done',
startDate: '2026-04-13', endDate: '2026-04-16', durationDays: 4,
progressPercent: 100, calendarId: CALENDAR_ID, isCritical: false, tags: [],
},
{
id: 't6', projectId: PROJECT_ID, parentId: 't1',
wbsCode: '1.5', name: 'Discovery Sign-off', type: 'milestone',
status: 'done',
startDate: '2026-04-17', endDate: '2026-04-17', durationDays: 0,
progressPercent: 100, calendarId: CALENDAR_ID, isCritical: true, tags: ['milestone'],
},
{
id: 't7', projectId: PROJECT_ID, parentId: null,
wbsCode: '2', name: 'Design', type: 'summary',
status: 'in-progress',
startDate: '2026-04-20', endDate: '2026-05-08', durationDays: 15,
progressPercent: 55, calendarId: CALENDAR_ID, isCritical: true, tags: [],
},
{
id: 't8', projectId: PROJECT_ID, parentId: 't7',
wbsCode: '2.1', name: 'Information Architecture', type: 'task',
status: 'done',
startDate: '2026-04-20', endDate: '2026-04-23', durationDays: 4,
progressPercent: 100, calendarId: CALENDAR_ID, isCritical: true, tags: [],
},
{
id: 't9', projectId: PROJECT_ID, parentId: 't7',
wbsCode: '2.2', name: 'Wireframes', type: 'task',
status: 'done',
startDate: '2026-04-24', endDate: '2026-04-29', durationDays: 4,
progressPercent: 100, calendarId: CALENDAR_ID, isCritical: true, tags: [],
},
{
id: 't10', projectId: PROJECT_ID, parentId: 't7',
wbsCode: '2.3', name: 'Design System Updates', type: 'task',
status: 'in-progress',
startDate: '2026-04-27', endDate: '2026-05-01', durationDays: 5,
progressPercent: 70, calendarId: CALENDAR_ID, isCritical: false, tags: [],
},
{
id: 't11', projectId: PROJECT_ID, parentId: 't7',
wbsCode: '2.4', name: 'Visual Design', type: 'task',
status: 'in-progress',
startDate: '2026-04-30', endDate: '2026-05-07', durationDays: 6,
progressPercent: 45, calendarId: CALENDAR_ID, isCritical: true, tags: [],
},
{
id: 't12', projectId: PROJECT_ID, parentId: 't7',
wbsCode: '2.5', name: 'Prototype Review', type: 'task',
status: 'not-started',
startDate: '2026-05-05', endDate: '2026-05-07', durationDays: 3,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: false, tags: [],
},
{
id: 't13', projectId: PROJECT_ID, parentId: 't7',
wbsCode: '2.6', name: 'Design Approval', type: 'milestone',
status: 'not-started',
startDate: '2026-05-08', endDate: '2026-05-08', durationDays: 0,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: true, tags: ['milestone'],
},
{
id: 't14', projectId: PROJECT_ID, parentId: null,
wbsCode: '3', name: 'Development', type: 'summary',
status: 'not-started',
startDate: '2026-05-11', endDate: '2026-06-05', durationDays: 20,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: true, tags: [],
},
{
id: 't15', projectId: PROJECT_ID, parentId: 't14',
wbsCode: '3.1', name: 'Frontend Shell', type: 'task',
status: 'not-started',
startDate: '2026-05-11', endDate: '2026-05-15', durationDays: 5,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: true, tags: [],
},
{
id: 't16', projectId: PROJECT_ID, parentId: 't14',
wbsCode: '3.2', name: 'CMS Integration', type: 'task',
status: 'not-started',
startDate: '2026-05-11', endDate: '2026-05-20', durationDays: 8,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: false, tags: [],
},
{
id: 't17', projectId: PROJECT_ID, parentId: 't14',
wbsCode: '3.3', name: 'Reusable Page Sections', type: 'task',
status: 'not-started',
startDate: '2026-05-18', endDate: '2026-05-27', durationDays: 8,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: true, tags: [],
},
{
id: 't18', projectId: PROJECT_ID, parentId: 't14',
wbsCode: '3.4', name: 'Search Experience', type: 'task',
status: 'not-started',
startDate: '2026-05-19', endDate: '2026-05-26', durationDays: 6,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: false, tags: [],
},
{
id: 't19', projectId: PROJECT_ID, parentId: 't14',
wbsCode: '3.5', name: 'Analytics Events', type: 'task',
status: 'not-started',
startDate: '2026-05-25', endDate: '2026-05-29', durationDays: 5,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: false, tags: [],
},
{
id: 't20', projectId: PROJECT_ID, parentId: 't14',
wbsCode: '3.6', name: 'Accessibility Pass', type: 'task',
status: 'not-started',
startDate: '2026-05-28', endDate: '2026-06-02', durationDays: 4,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: true, tags: [],
},
{
id: 't21', projectId: PROJECT_ID, parentId: 't14',
wbsCode: '3.7', name: 'Performance Tuning', type: 'task',
status: 'not-started',
startDate: '2026-06-01', endDate: '2026-06-04', durationDays: 4,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: true, tags: [],
},
{
id: 't22', projectId: PROJECT_ID, parentId: 't14',
wbsCode: '3.8', name: 'Feature Complete', type: 'milestone',
status: 'not-started',
startDate: '2026-06-05', endDate: '2026-06-05', durationDays: 0,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: true, tags: ['milestone'],
},
{
id: 't23', projectId: PROJECT_ID, parentId: null,
wbsCode: '4', name: 'QA and Release Prep', type: 'summary',
status: 'not-started',
startDate: '2026-06-08', endDate: '2026-06-18', durationDays: 9,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: true, tags: [],
},
{
id: 't24', projectId: PROJECT_ID, parentId: 't23',
wbsCode: '4.1', name: 'Test Plan', type: 'task',
status: 'not-started',
startDate: '2026-06-08', endDate: '2026-06-10', durationDays: 3,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: false, tags: [],
},
{
id: 't25', projectId: PROJECT_ID, parentId: 't23',
wbsCode: '4.2', name: 'Cross-browser QA', type: 'task',
status: 'not-started',
startDate: '2026-06-10', endDate: '2026-06-15', durationDays: 4,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: true, tags: [],
},
{
id: 't26', projectId: PROJECT_ID, parentId: 't23',
wbsCode: '4.3', name: 'Content QA', type: 'task',
status: 'not-started',
startDate: '2026-06-11', endDate: '2026-06-16', durationDays: 4,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: false, tags: [],
},
{
id: 't27', projectId: PROJECT_ID, parentId: 't23',
wbsCode: '4.4', name: 'Release Candidate', type: 'milestone',
status: 'not-started',
startDate: '2026-06-18', endDate: '2026-06-18', durationDays: 0,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: true, tags: ['milestone'],
},
{
id: 't28', projectId: PROJECT_ID, parentId: null,
wbsCode: '5', name: 'Launch', type: 'task',
status: 'not-started',
startDate: '2026-06-19', endDate: '2026-06-23', durationDays: 3,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: true, tags: [],
},
{
id: 't29', projectId: PROJECT_ID, parentId: null,
wbsCode: '6', name: 'Post-launch Review', type: 'milestone',
status: 'not-started',
startDate: '2026-06-26', endDate: '2026-06-26', durationDays: 0,
progressPercent: 0, calendarId: CALENDAR_ID, isCritical: false, tags: ['milestone'],
},
];
export const dependencies: DependencyEntity[] = [
{ id: 'd1', predecessorTaskId: 't2', successorTaskId: 't5', type: 'finish-to-start', lagDays: 0 },
{ id: 'd2', predecessorTaskId: 't3', successorTaskId: 't5', type: 'finish-to-start', lagDays: 0 },
{ id: 'd3', predecessorTaskId: 't4', successorTaskId: 't6', type: 'finish-to-start', lagDays: 0 },
{ id: 'd4', predecessorTaskId: 't5', successorTaskId: 't6', type: 'finish-to-start', lagDays: 0 },
{ id: 'd5', predecessorTaskId: 't6', successorTaskId: 't8', type: 'finish-to-start', lagDays: 1 },
{ id: 'd6', predecessorTaskId: 't8', successorTaskId: 't9', type: 'finish-to-start', lagDays: 0 },
{ id: 'd7', predecessorTaskId: 't9', successorTaskId: 't11', type: 'finish-to-start', lagDays: 0 },
{ id: 'd8', predecessorTaskId: 't10', successorTaskId: 't12', type: 'finish-to-start', lagDays: 0 },
{ id: 'd9', predecessorTaskId: 't11', successorTaskId: 't13', type: 'finish-to-start', lagDays: 0 },
{ id: 'd10', predecessorTaskId: 't12', successorTaskId: 't13', type: 'finish-to-start', lagDays: 0 },
{ id: 'd11', predecessorTaskId: 't13', successorTaskId: 't15', type: 'finish-to-start', lagDays: 1 },
{ id: 'd12', predecessorTaskId: 't15', successorTaskId: 't17', type: 'finish-to-start', lagDays: 0 },
{ id: 'd13', predecessorTaskId: 't16', successorTaskId: 't18', type: 'finish-to-start', lagDays: 0 },
{ id: 'd14', predecessorTaskId: 't17', successorTaskId: 't20', type: 'finish-to-start', lagDays: 0 },
{ id: 'd15', predecessorTaskId: 't18', successorTaskId: 't19', type: 'finish-to-start', lagDays: 0 },
{ id: 'd16', predecessorTaskId: 't19', successorTaskId: 't21', type: 'finish-to-start', lagDays: 0 },
{ id: 'd17', predecessorTaskId: 't20', successorTaskId: 't21', type: 'finish-to-start', lagDays: 0 },
{ id: 'd18', predecessorTaskId: 't21', successorTaskId: 't22', type: 'finish-to-start', lagDays: 0 },
{ id: 'd19', predecessorTaskId: 't22', successorTaskId: 't24', type: 'finish-to-start', lagDays: 1 },
{ id: 'd20', predecessorTaskId: 't24', successorTaskId: 't25', type: 'finish-to-start', lagDays: 0 },
{ id: 'd21', predecessorTaskId: 't24', successorTaskId: 't26', type: 'finish-to-start', lagDays: 0 },
{ id: 'd22', predecessorTaskId: 't25', successorTaskId: 't27', type: 'finish-to-start', lagDays: 0 },
{ id: 'd23', predecessorTaskId: 't26', successorTaskId: 't27', type: 'finish-to-start', lagDays: 0 },
{ id: 'd24', predecessorTaskId: 't27', successorTaskId: 't28', type: 'finish-to-start', lagDays: 0 },
{ id: 'd25', predecessorTaskId: 't28', successorTaskId: 't29', type: 'finish-to-start', lagDays: 2 },
];
Vue vue
<template>
<section class="gantt-basic-demo">
<div ref="toolbarRef" class="gantt-basic-toolbar"></div>
<RevoGrid
ref="gridRef"
class="gantt-basic-grid"
hide-attribution
:theme="isDark ? 'darkCompact' : 'compact'"
:plugins="plugins"
:source="tasks"
:columns="columns"
:gantt.prop="ganttConfig"
:gantt-dependencies.prop="dependencies"
:gantt-calendars.prop="calendars"
/>
</section>
</template>
<script setup lang="ts">
import { nextTick, onBeforeUnmount, onMounted, ref } from 'vue';
import RevoGrid from '@revolist/vue3-datagrid';
import { GanttPlugin, createDefaultTaskTableColumn, defineGanttToolbar } from '@revolist/revogrid-enterprise';
import { currentThemeVue } from '../composables/useRandomData';
import { calendars as basicCalendars, dependencies as basicDependencies, ganttConfig as basicGanttConfig, tasks as basicTasks, taskTableColumnProps, toolbarColumns } from './gantt-basic-data';
import './gantt-basic.css';
const { isDark } = currentThemeVue();
const plugins = ref([GanttPlugin]);
const ganttConfig = ref(basicGanttConfig);
const calendars = ref(basicCalendars);
const tasks = ref(basicTasks.map((task) => ({ ...task })));
const dependencies = ref(basicDependencies);
const columns = ref(taskTableColumnProps.map((prop) => createDefaultTaskTableColumn(prop)));
const gridRef = ref<InstanceType<typeof RevoGrid> | HTMLRevoGridElement | null>(null);
const toolbarRef = ref<HTMLElement | null>(null);
let toolbarMounted = false;
let toolbarFrame = 0;
function getGridEl(): HTMLRevoGridElement | null {
const refValue = gridRef.value as (InstanceType<typeof RevoGrid> & { $el?: HTMLRevoGridElement }) | HTMLRevoGridElement | null;
const candidate = (refValue && '$el' in refValue ? refValue.$el : refValue) ?? null;
return candidate instanceof HTMLElement && candidate.tagName.toLowerCase() === 'revo-grid'
? candidate as HTMLRevoGridElement
: null;
}
function mountToolbar() {
if (toolbarMounted) {
return;
}
const grid = getGridEl();
if (!toolbarRef.value || !grid) {
toolbarFrame = requestAnimationFrame(mountToolbar);
return;
}
toolbarMounted = true;
defineGanttToolbar(toolbarRef.value, {
grid,
columns: toolbarColumns,
controls: {
export: false,
baseline: false,
},
});
}
onMounted(async () => {
await nextTick();
mountToolbar();
});
onBeforeUnmount(() => {
if (toolbarFrame) {
cancelAnimationFrame(toolbarFrame);
}
if (toolbarRef.value) {
toolbarRef.value.textContent = '';
}
});
</script>
React tsx
// src/components/gantt/GanttBasic.tsx
import React, { useEffect, useMemo, useRef } from 'react';
import { RevoGrid } from '@revolist/react-datagrid';
import { GanttPlugin, createDefaultTaskTableColumn, defineGanttToolbar } from '@revolist/revogrid-enterprise';
import { currentTheme } from '../composables/useRandomData';
import { calendars, dependencies, ganttConfig, tasks, taskTableColumnProps, toolbarColumns } from './gantt-basic-data';
import './gantt-basic.css';
const { isDark } = currentTheme();
function GanttBasic() {
const gridRef = useRef<HTMLRevoGridElement>(null);
const toolbarRef = useRef<HTMLDivElement>(null);
const project = useMemo(() => ganttConfig, []);
const source = useMemo(() => tasks.map((task) => ({ ...task })), []);
const columns = useMemo(() => taskTableColumnProps.map((prop) => createDefaultTaskTableColumn(prop)), []);
useEffect(() => {
const toolbar = toolbarRef.current;
const grid = gridRef.current;
if (!toolbar || !grid) {
return undefined;
}
defineGanttToolbar(toolbar, {
grid,
columns: toolbarColumns,
controls: {
export: false,
baseline: false,
},
});
return () => {
toolbar.textContent = '';
};
}, [columns]);
return (
<section className="gantt-basic-demo">
<div ref={toolbarRef} className="gantt-basic-toolbar" />
<RevoGrid
ref={gridRef}
className="gantt-basic-grid"
theme={isDark() ? 'darkCompact' : 'compact'}
hideAttribution
plugins={[GanttPlugin]}
source={source}
columns={columns}
gantt={project}
ganttDependencies={dependencies}
ganttCalendars={calendars}
/>
</section>
);
}
export default GanttBasic;
Angular ts
// src/components/gantt/GanttBasicAngular.ts
import { AfterViewInit, Component, ElementRef, NO_ERRORS_SCHEMA, ViewChild, ViewEncapsulation } from '@angular/core';
import { RevoGrid } from '@revolist/angular-datagrid';
import { GanttPlugin, createDefaultTaskTableColumn, defineGanttToolbar } from '@revolist/revogrid-enterprise';
import { currentTheme } from '../composables/useRandomData';
import { calendars as basicCalendars, dependencies as basicDependencies, ganttConfig as basicGanttConfig, tasks as basicTasks, taskTableColumnProps, toolbarColumns } from './gantt-basic-data';
@Component({
selector: 'gantt-basic-grid',
standalone: true,
// Allows Angular demos to bind RevoGrid plugin props that are not wrapper inputs.
schemas: [NO_ERRORS_SCHEMA],
imports: [RevoGrid],
template: `
<section class="gantt-basic-demo">
<div #toolbar class="gantt-basic-toolbar"></div>
<revo-grid
#grid
class="gantt-basic-grid"
[theme]="theme"
[hideAttribution]="true"
[plugins]="plugins"
[source]="tasks"
[columns]="columns"
[gantt]="ganttConfig"
[ganttDependencies]="dependencies"
[ganttCalendars]="calendars"
></revo-grid>
</section>
`,
styleUrls: ['./gantt-basic.css'],
encapsulation: ViewEncapsulation.None,
})
export class GanttBasicGridComponent implements AfterViewInit {
@ViewChild('grid', { read: ElementRef }) gridRef!: ElementRef<HTMLRevoGridElement>;
@ViewChild('toolbar', { read: ElementRef }) toolbarRef!: ElementRef<HTMLElement>;
theme = currentTheme().isDark() ? 'darkCompact' : 'compact';
plugins = [GanttPlugin];
ganttConfig = basicGanttConfig;
calendars = basicCalendars;
tasks = basicTasks.map((task) => ({ ...task }));
dependencies = basicDependencies;
columns = taskTableColumnProps.map((prop) => createDefaultTaskTableColumn(prop));
ngAfterViewInit(): void {
defineGanttToolbar(this.toolbarRef.nativeElement, {
grid: this.gridRef.nativeElement,
columns: toolbarColumns,
controls: {
export: false,
baseline: false,
},
});
}
}
Common checks:
- Missing
ganttCalendarsor mismatchedcalendarId. - Duplicate IDs in tasks/dependencies/resources/assignments.
- Dependency points to missing task ID.
- Invalid task date ranges or malformed constraints.
- No visible timeline because viewport/zoom span does not include task dates.
Validation and diagnostics are produced by:
engine/scheduler-validation.tsengine/scheduler-types.ts