GanttEx

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:

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

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.