Interactive Gantt charts for Phoenix LiveView, inspired by DHTMLX Gantt.

State, validation, layout and dialogs live on the server. The only JavaScript is one small colocated hook for what needs the mouse: dragging, resizing and drawing dependencies.

<.live_component module={GanttEx.Live.Gantt} id="gantt" tasks={@tasks} links={@links} locale="es" />

Features

These are the features of the DHTMLX Gantt community edition:

  • Task grid: tree, configurable columns (slots), sorting, resizable columns and grid, inline editing
  • Task types: tasks, projects (dates rolled up from their children) and milestones
  • Drag & drop: move, resize and change progress, with snapping; reorder and re-parent rows
  • Dependencies: finish-to-start, start-to-start, finish-to-finish and start-to-finish with lag, drawn by dragging between bar edges, with cycle detection
  • Zoomable time scale: hours, days, weeks, months, quarters and years, or your own levels
  • Lightbox editor with configurable sections and custom fields, quick info popup, tooltips and confirmation dialogs
  • Drag to create tasks on the timeline and drag to pan, with edge auto-scrolling
  • Smart rendering: large charts only render the rows around the viewport
  • Keyboard navigation, fullscreen and print (PDF)
  • Export to JSON (DHTMLX format), CSV/Excel, iCalendar, MS Project XML, SVG and PNG; import from DHTMLX JSON/XML and MS Project XML
  • 8 languages: English, Spanish, French, Italian, German, Portuguese, Brazilian Portuguese and Japanese (Gettext .po files)
  • Light and dark themes based on CSS custom properties, WAI-ARIA roles, touch support and reduced motion
  • Events for persistence: every change is sent to your LiveView as {GanttEx, %GanttEx.Event{}}

And the features of the PRO edition (see the Advanced features guide):

  • Working-time calendars with holidays and per-task calendars
  • Auto-scheduling with the eight task constraints, strict mode and ALAP
  • Critical path and total/free slack
  • Baselines and deadlines with overdue detection
  • Resources: assignments, load histogram and overload detection
  • Grouping by any field or by resource
  • Split tasks and rollups
  • Undo/redo, multi-selection and multi-drag
  • Timeline markers, WBS codes, dynamic loading and auto types

Installation

Add gantt_ex to your dependencies (Phoenix 1.8+, LiveView 1.2+):

def deps do
  [
    {:gantt_ex, "~> 0.1.0"}
  ]
end

Register the hook in assets/js/app.js:

import {hooks as ganttHooks} from "phoenix-colocated/gantt_ex"

const liveSocket = new LiveSocket("/live", Socket, {
  hooks: {...colocatedHooks, ...ganttHooks},
  // ...
})

Import the styles in assets/css/app.css (Tailwind 4.2.3+):

@import "phoenix-colocated/gantt_ex/colocated.css";

New Phoenix 1.8 applications already have the NODE_PATH and compiler configuration needed to resolve phoenix-colocated. See Phoenix.LiveView.ColocatedJS if yours does not.

Usage

defmodule MyAppWeb.ProjectLive do
  use MyAppWeb, :live_view

  def mount(_params, _session, socket) do
    {:ok, assign(socket, tasks: Planning.list_tasks(), links: Planning.list_links())}
  end

  def render(assigns) do
    ~H"""
    <Layouts.app flash={@flash}>
      <.live_component module={GanttEx.Live.Gantt} id="gantt" tasks={@tasks} links={@links} />
    </Layouts.app>
    """
  end

  # Persist every change, then re-render the chart with fresh data.
  def handle_info({GanttEx, %GanttEx.Event{} = event}, socket) do
    :ok = Planning.apply_event(event)
    {:noreply, assign(socket, tasks: Planning.list_tasks(), links: Planning.list_links())}
  end
end

Tasks can be maps, keyword lists or structs (Ecto schemas included) with DHTMLX field names: id, text, start_date, end_date, duration, progress (0..1), parent (or parent_id), type and open. Any other field ends up in task.meta and can be shown in custom columns.

<.live_component module={GanttEx.Live.Gantt} id="gantt" tasks={@tasks} links={@links} zoom={:week}>
  <:column field={:text} tree />
  <:column field={:owner} label="Owner" editor={:text} :let={task}>{task.meta[:owner]}</:column>
  <:column field={:start_date} />
  <:column field={:duration} />
  <:column field={:add} />
</.live_component>

Guides

Example application

example/live_gantt is a Phoenix application that stores a project in Postgres:

cd example/live_gantt
mix setup
mix phx.server

Development

mix test       # unit tests, LiveView tests and doctests
mix docs       # documentation
mix precommit  # compile with warnings as errors, format and test

License

MIT, see the LICENSE file.