GanttRepeat

Gantt charts illustrate project schedules. They show the start and finish dates of each task and typically add information such as the completion state of each task and dependencies between tasks.

This sample shows how you can use the FlexChart to create a Gantt chart with repeating tasks.

It does this by adding data items with the same (numeric) "X" value.

The Y axis has an itemFormatter that replaces the bound X values (index) with the task names.

import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; import { FlexChart } from '@grapecity/wijmo.chart'; import { format } from '@grapecity/wijmo'; import { getData } from './data'; document.readyState === 'complete' ? init() : window.onload = init; function init() { // create simple Gantt chart var theChart = new FlexChart('#theChart', { itemsSource: getData(), chartType: 'Bar', bindingX: 'index', series: [ { binding: 'start,end' } ], axisY: { majorGrid: false, minorGrid: true, reversed: true, itemFormatter: formatter }, plotMargin: 'auto auto auto 180', tooltip: { content: getTooltipContent } }); // replace item index with item name in Y axis function formatter(engine, label) { var data = theChart.itemsSource; var item = data.find(item => item.index == label.val); label.text = item.name; return label; } // show task name and duraction in tooltip function getTooltipContent(ht) { var str = format('<b>{name}</b>:<br/>{start:d} - {end:d}', { name: ht.item.name, start: ht.item.start, end: ht.item.end }); return str; } } <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Wijmo FlexChart Gantt</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app'); </script> </head> <body> <div class="container-fluid"> <div id="theChart"></div> </div> </body> </html> import { DateTime } from '@grapecity/wijmo'; export function getData() { let data = []; let date = new Date(); // add some regular tasks for (let i = 0; i < 3; i++) { let low = i + Math.ceil(Math.random() * 10); let high = low + Math.ceil(Math.random() * 10); data.push({ index: i, name: 'Regular Task ' + (i + 1), start: new Date(date.getTime() + low * 3600 * 24 * 1000), end: new Date(date.getTime() + high * 3600 * 24 * 1000) }); } // add a repeating task (same "index" value) let dt = data[0].start; for (let i = 0; i < 5; i++) { data.push({ index: 3, name: 'First Repeating Task', start: dt, end: DateTime.addDays(dt, 4) }); dt = DateTime.addDays(dt, 7); } // add another repeating task dt = DateTime.addDays(data[0].start, 2); for (let i = 0; i < 5; i++) { data.push({ index: 4, name: 'Second Repeating Task', start: dt, end: DateTime.addDays(dt, 5) }); dt = DateTime.addDays(dt, 7); } // done return data; } body { margin-bottom: 24pt; } import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; import { Component, Inject, enableProdMode, NgModule } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { BrowserModule } from '@angular/platform-browser'; import { WjChartModule } from '@grapecity/wijmo.angular2.chart'; import { DataService, TTask } from './app.data'; import { HitTestInfo } from '@grapecity/wijmo.chart'; import { format } from '@grapecity/wijmo'; @Component({ selector: 'app-component', templateUrl: 'src/app.component.html' }) export class AppComponent { data: TTask[]; formatter = this.axisLabelFormatter.bind(this); constructor(@Inject(DataService) private dataService: DataService) { this.data = dataService.getData(); } // render task name instead of index on y axis axisLabelFormatter(engine: any, label: any) { var data = this.data; var item = data.find(item => item.index == label.val); label.text = item.name; return label; } // show task name and duraction in tooltip getTooltipContent(ht: HitTestInfo): string { var str = format('<b>{name}</b>:<br/>{start:d} - {end:d}', { name: ht.item.name, start: ht.item.start, end: ht.item.end }); return str; } } @NgModule({ imports: [WjChartModule, BrowserModule], declarations: [AppComponent], providers: [DataService], bootstrap: [AppComponent] }) export class AppModule { } enableProdMode(); // Bootstrap application with hash style navigation and global services. platformBrowserDynamic().bootstrapModule(AppModule); <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Wijmo FlexChart Gantt</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Polyfills --> <script src="node_modules/core-js/client/shim.min.js"></script> <script src="node_modules/zone.js/dist/zone.min.js"></script> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.js"></script> <script src="systemjs.config.js"></script> <script> // workaround to load 'rxjs/operators' from the rxjs bundle System.import('rxjs').then(function (m) { System.set(SystemJS.resolveSync('rxjs/operators'), System.newModule(m.operators)); System.import('./src/app.component'); }); </script> </head> <body> <app-component></app-component> </body> </html> <div class="container-fluid"> <wj-flex-chart [itemsSource]="data" chartType="Bar" bindingX="index" plotMargin="auto auto auto 180" [tooltipContent]="getTooltipContent"> <wj-flex-chart-series binding="start,end"> </wj-flex-chart-series> <wj-flex-chart-axis wjProperty="axisY" [majorGrid]="false" [minorGrid]="true" [reversed]="true" [itemFormatter]="formatter"> </wj-flex-chart-axis> </wj-flex-chart> </div> import { DateTime } from '@grapecity/wijmo'; import { Injectable } from '@angular/core'; export type TTask = { index: number; name: string; start: Date; end: Date; }; @Injectable() export class DataService { getData(): TTask[] { let data = []; let date = new Date(); // add some regular tasks for (let i = 0; i < 3; i++) { let low = i + Math.ceil(Math.random() * 10); let high = low + Math.ceil(Math.random() * 10); data.push({ index: i, name: 'Regular Task ' + (i + 1), start: new Date(date.getTime() + low * 3600 * 24 * 1000), end: new Date(date.getTime() + high * 3600 * 24 * 1000) }); } // add a repeating task (same "index" value) let dt = data[0].start; for (let i = 0; i < 5; i++) { data.push({ index: 3, name: 'First Repeating Task', start: dt, end: DateTime.addDays(dt, 4) }); dt = DateTime.addDays(dt, 7); } // add another repeating task dt = DateTime.addDays(data[0].start, 2); for (let i = 0; i < 5; i++) { data.push({ index: 4, name: 'Second Repeating Task', start: dt, end: DateTime.addDays(dt, 5) }); dt = DateTime.addDays(dt, 7); } // done return data; } } body { margin-bottom: 24pt; } <template> <div class="container-fluid"> <wj-flex-chart :itemsSource="data" chartType="Bar" bindingX="index" plotMargin="auto auto auto 180" :tooltipContent="getTooltipContent"> <wj-flex-chart-series binding="start,end"> </wj-flex-chart-series> <wj-flex-chart-axis wjProperty="axisY" :majorGrid="false" :minorGrid="true" :reversed="true" :itemFormatter="formatter"> </wj-flex-chart-axis> </wj-flex-chart> </div> </template> <script> import '@grapecity/wijmo.styles/wijmo.css'; import 'bootstrap.css'; import Vue from 'vue'; import '@grapecity/wijmo.vue2.chart'; import { format } from '@grapecity/wijmo'; import { getData } from './data'; new Vue({ el: '#app', data: { data: getData() }, methods: { // show task name and duraction in tooltip getTooltipContent(ht) { var str = format('<b>{name}</b>:<br/>{start:d} - {end:d}', { name: ht.item.name, start: ht.item.start, end: ht.item.end }); return str; }, // replace item index with item name in Y axis formatter(engine, label) { var item = this.data.find(item => item.index == label.val); label.text = item.name; return label; } } }); </script> <style> body { margin-bottom: 24pt; } </style> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Wijmo FlexChart Gantt</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app.vue'); </script> </head> <body> <div id="app"></div> </body> </html> import { DateTime } from '@grapecity/wijmo'; export function getData() { let data = []; let date = new Date(); // add some regular tasks for (let i = 0; i < 3; i++) { let low = i + Math.ceil(Math.random() * 10); let high = low + Math.ceil(Math.random() * 10); data.push({ index: i, name: 'Regular Task ' + (i + 1), start: new Date(date.getTime() + low * 3600 * 24 * 1000), end: new Date(date.getTime() + high * 3600 * 24 * 1000) }); } // add a repeating task (same "index" value) let dt = data[0].start; for (let i = 0; i < 5; i++) { data.push({ index: 3, name: 'First Repeating Task', start: dt, end: DateTime.addDays(dt, 4) }); dt = DateTime.addDays(dt, 7); } // add another repeating task dt = DateTime.addDays(data[0].start, 2); for (let i = 0; i < 5; i++) { data.push({ index: 4, name: 'Second Repeating Task', start: dt, end: DateTime.addDays(dt, 5) }); dt = DateTime.addDays(dt, 7); } // done return data; } import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './app.css'; // import * as React from 'react'; import * as ReactDOM from 'react-dom'; // import * as wijmo from '@grapecity/wijmo'; import * as wjChart from '@grapecity/wijmo.react.chart'; import { getData } from './data'; class App extends React.Component { constructor(props) { super(props); this.chartInitialized = (sender) => { sender.tooltip.content = this.getTooltipContent; }; this.getTooltipContent = (ht) => { var str = wijmo.format('<b>{name}</b>:<br/>{start:d} - {end:d}', { name: ht.item.name, start: ht.item.start, end: ht.item.end }); return str; }; // replace item index with item name in Y axis this.formatter = (engine, label) => { var item = this.state.data.find((item) => item.index == label.val); label.text = item.name; return label; }; this.state = { data: getData() }; } render() { return <div className="container-fluid"> <wjChart.FlexChart itemsSource={this.state.data} chartType="Bar" bindingX="index" plotMargin="auto auto auto 180" initialized={this.chartInitialized}> <wjChart.FlexChartSeries binding="start,end"/> <wjChart.FlexChartAxis wjProperty="axisY" majorGrid={false} minorGrid={true} reversed={true} itemFormatter={this.formatter}/> </wjChart.FlexChart> </div>; } } ReactDOM.render(<App />, document.getElementById('app')); <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>AutoComplete</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app'); </script> </head> <body> <div id="app"></div> </body> </html> body { margin-bottom: 24pt; } import { DateTime } from '@grapecity/wijmo'; export function getData() { let data = []; let date = new Date(); // add some regular tasks for (let i = 0; i < 3; i++) { let low = i + Math.ceil(Math.random() * 10); let high = low + Math.ceil(Math.random() * 10); data.push({ index: i, name: 'Regular Task ' + (i + 1), start: new Date(date.getTime() + low * 3600 * 24 * 1000), end: new Date(date.getTime() + high * 3600 * 24 * 1000) }); } // add a repeating task (same "index" value) let dt = data[0].start; for (let i = 0; i < 5; i++) { data.push({ index: 3, name: 'First Repeating Task', start: dt, end: DateTime.addDays(dt, 4) }); dt = DateTime.addDays(dt, 7); } // add another repeating task dt = DateTime.addDays(data[0].start, 2); for (let i = 0; i < 5; i++) { data.push({ index: 4, name: 'Second Repeating Task', start: dt, end: DateTime.addDays(dt, 5) }); dt = DateTime.addDays(dt, 7); } // done return data; }