Blazor-ApexGantt renders an interactive project timeline from a C# task collection. You render <ApexGantt> in Razor and hand it a List<GanttTask> and a GanttOptions, both strongly typed. Version 1.3.0 tracks core 3.15 and bundles it as a self-contained ES module, so there is no npm, no bundler and no script tag.

dotnet add package Blazor-ApexGantt
@using Blazor_ApexGantt.Components
@using Blazor_ApexGantt.Models
@rendermode InteractiveServer

<ApexGantt Options="@options" Tasks="@tasks" />

@code {
    private GanttOptions options = new()
    {
        Width = "100%",
        Height = "500px"
    };

    private List<GanttTask> tasks = new()
    {
        new GanttTask
        {
            Id = "design",
            Name = "Design",
            StartTime = new DateTime(2026, 1, 1),
            EndTime = new DateTime(2026, 1, 15),
            Progress = 45
        },
        new GanttTask
        {
            Id = "build",
            Name = "Build",
            StartTime = new DateTime(2026, 1, 16),
            EndTime = new DateTime(2026, 2, 28),
            Dependency = "design"
        },
        // No EndTime, so this renders as a milestone diamond on its start date.
        new GanttTask
        {
            Id = "launch",
            Name = "Launch",
            StartTime = new DateTime(2026, 3, 5)
        }
    };
}

Two constraints to know before you plan around it. It targets .NET 9 only, unlike the chart and data grid packages which cover .NET 8, 9 and 10. And ApexGantt is Premium and above with no free tier: the revenue threshold that makes some Apex products free does not apply, so without a key the chart carries an evaluation watermark at any revenue.

A Timeline Is a Projection of Your Task List

Hand the component a List<GanttTask> and the timeline is what comes out. Dates take a DateTime or a string, Dependency takes a task id or a TaskDependency with a type and lag, and ParentId nests tasks. Nothing asks you to reshape your domain model into a chart configuration first.


Critical Path Without the Arithmetic

Set EnableCriticalPath and the engine walks the dependency graph and highlights the chain that decides the end date. CriticalBarColor and CriticalArrowColor style it. Combined with a working calendar and working-day lag units, the path reflects the schedule your team actually works.


Planned Against Actual

Each GanttTask takes a Baseline with its planned dates, drawn below the actual bar once baselines are enabled on the options. Slippage becomes visible rather than something you compute in a report, and the comparison travels in the same task objects as everything else.


Continuous Zoom, Not Fixed View Modes

PixelsPerDay replaced the old view-mode presets in 1.3.0. Roughly 40 reads as a week, 12 a month and 4 a quarter, and leaving it off auto-fits the data span. ZoomInAsync and ZoomOutAsync step it at runtime, so a day view and a year view are the same option at different values.

One Package, No Toolchain

Since 1.3.0 the engine is vendored as a self-contained ES module and imported by the package itself. No npm, CDN or script tag.

Typed Tasks and Options

GanttTask and over eighty GanttOptions properties as typed C#, so an option name or enum value is checked at build time.

Dependencies with Lag

FS, FF, SF and SS relationships, with lag or lead in working days or calendar days.

Milestones

A task with no EndTime renders as a diamond on its start date. No special case, no separate collection.

Critical Path and Baselines

Both are option flags. The engine walks the graph and draws the planned bar under the actual one.

Undo and Redo

Built-in history with CanUndoAsync and CanRedoAsync, plus an OnHistoryChange callback to drive your own toolbar.

Twenty Typed Events

Drag, resize, add, delete, move, progress, dependency, selection, sort, filter, group, column and validation events as EventCallbacks.

.NET 9 Only, Premium Plan

Targets .NET 9, not .NET 8. ApexGantt has no free tier: without a key the chart carries an evaluation watermark at any revenue.

Add a Gantt Chart to a Blazor App

Three steps. Start with the package:

dotnet add package Blazor-ApexGantt

Register the services in Program.cs. This step is required, not optional, and it is where the license key goes:

using Blazor_ApexGantt.Extensions;

builder.Services.AddApexGantt(options =>
{
    options.LicenseKey = "APEX-...";
});

Then add the namespaces to _Imports.razor. Note the underscores: the NuGet package is Blazor-ApexGantt but the C# namespace is Blazor_ApexGantt, because a hyphen is not legal in an identifier.

@using Blazor_ApexGantt.Components
@using Blazor_ApexGantt.Models

Nothing is copied into wwwroot and there is no script tag. Since 1.3.0 the package vendors the timeline engine and imports it itself as a static web asset.

Dependencies That Carry Their Own Semantics

The simple case stays simple: set Dependency to a task id string and you get Finish-to-Start with zero lag. When the relationship is the point, pass a TaskDependency instead.

new GanttTask
{
    Id = "qa",
    Name = "QA",
    StartTime = new DateTime(2026, 2, 20),
    EndTime = new DateTime(2026, 3, 4),
    // A plain string is Finish-to-Start with zero lag.
    // A TaskDependency spells the relationship out.
    Dependency = new TaskDependency
    {
        TaskId = "build",
        Type = DependencyType.SS,
        Lag = 3,
        LagUnit = LagUnit.Working
    }
}

DependencyType covers FS, FF, SF and SS. Lag is an integer that goes negative for lead, and LagUnit decides whether those are working days, which respects the calendar, or raw calendar days.

A milestone needs no special type. Leave EndTime off a task and it renders as a diamond on its start date, which is what the third task in the hero above is doing. Type = TaskType.Milestone is available when you want to be explicit.

Scheduling Features Are Option Flags

Critical path, baselines, the working calendar and undo history are all configuration rather than code you write:

private GanttOptions options = new()
{
    Height = "500px",
    EnableCriticalPath = true,
    CriticalBarColor = "#DC2626",
    Baseline = new BaselineOptions { Enabled = true },
    Calendar = new CalendarOptions { WorkingWeekdays = [1, 2, 3, 4, 5] },
    History = new HistoryOptions { Enabled = true }
};

GanttOptions carries over eighty typed properties in this shape, covering appearance, column configuration, sorting, grouping, filtering, the crosshair, annotations, the project boundary, assignees, task segments and summary bars.

ViewMode is gone as of 1.3.0, along with EnableToolbar. Zoom is continuous through PixelsPerDay: roughly 40 reads as a week, 12 a month and 4 a quarter, and omitting it auto-fits the data span. Code written against 1.2.0 that sets ViewMode will not compile.

Drive the Timeline at Runtime

Hold the component with @ref and the whole runtime API is available as awaitable C#, rather than something you reach through JavaScript interop yourself.

<ApexGantt @ref="gantt" Options="@options" Tasks="@tasks"
           OnTaskDragged="OnDragged"
           OnHistoryChange="OnHistory" />

@code {
    private ApexGantt? gantt;

    private async Task AddPhase()
    {
        await gantt!.AddTaskAsync(new GanttTask
        {
            Id = "rollout",
            Name = "Rollout",
            StartTime = new DateTime(2026, 3, 6),
            EndTime = new DateTime(2026, 3, 20)
        });

        await gantt.AddDependencyAsync("launch", "rollout", DependencyType.FS, lag: 0);
        await gantt.ScrollToTaskAsync("rollout");
    }

    private void OnDragged(TaskDraggedEventArgs e) => MarkDirty(e.TaskId);
    private void OnHistory(HistoryChangeEventArgs e) => (canUndo, canRedo) = (e.CanUndo, e.CanRedo);
}

There are about thirty methods: task CRUD (AddTaskAsync, UpdateTaskAsync, DeleteTaskAsync, MoveTaskAsync), dependencies, UndoAsync and RedoAsync with CanUndoAsync and CanRedoAsync, sorting, grouping, filtering, column widths and order, selection, zoom and ExportChartAsync.

Twenty events come back as typed EventCallback parameters, including OnTaskDragged, OnTaskResized, OnDependencyAdded, OnHistoryChange and OnTaskValidationError. The validation and error events matter more here than on a chart: a user dragging a task can produce a schedule your domain rules reject, and those events are where you say so.

What This Package Does Not Cover

Custom HTML tooltips. In the core, the tooltip template is a JavaScript callback that receives the task and returns markup. The wrapper serializes options as plain JSON and has no mechanism for passing a function, so the template never runs. TooltipId sets the tooltip container's element id, which is a different thing. EnableTooltip and the tooltip colours all work, so this is about templating the contents, not having tooltips at all.

.NET 8. Worth repeating because it is the constraint most likely to stop a project: this package is .NET 9 only.

The AdditionalOptions bag on GanttOptions passes unmodeled keys straight through to the engine, which covers new core options before they are modelled. It cannot carry functions, for the reason above.

Blazor Gantt Chart FAQ

What is Blazor-ApexGantt?

Blazor-ApexGantt is a Blazor wrapper for the ApexGantt timeline engine. You render an ApexGantt component in Razor and hand it a List<GanttTask> plus a GanttOptions object, both strongly typed C#. Version 1.3.0 tracks core 3.15 and bundles it as a self-contained ES module inside the NuGet package, so there is no script tag, CDN reference or npm step.

Which .NET versions does Blazor-ApexGantt support?

Version 1.3.0 targets .NET 9 only. Unlike the chart and data grid packages, which multi-target .NET 8, 9 and 10, a .NET 8 LTS project cannot use it without moving framework. Check this before planning around it.

Is there a free tier for the Blazor Gantt chart?

No. ApexGantt is included in the Premium plan and above, and there is no free tier. The revenue threshold that makes some Apex products free does not apply here: a Premium license is required at any revenue, by companies, individuals, non-profits and educators alike. Without a valid key the chart renders with a trial watermark, which is for evaluation only.

How do I install the Blazor Gantt chart?

Run dotnet add package Blazor-ApexGantt, register the services with builder.Services.AddApexGantt in Program.cs, and add @using Blazor_ApexGantt.Components and @using Blazor_ApexGantt.Models to your _Imports.razor. The registration is where the license key goes, and unlike the data grid package it is required rather than optional.

How do I create a milestone in the Blazor Gantt chart?

Leave EndTime off the task. A GanttTask with a StartTime and no EndTime renders as a milestone diamond on that date. You can also set Type to TaskType.Milestone explicitly, and MilestoneColor on the options controls the diamond colour.

How do task dependencies work?

The Dependency property takes either a plain task-id string, which means Finish-to-Start with zero lag, or a TaskDependency object for a typed relationship. TaskDependency carries TaskId, a DependencyType of FS, FF, SF or SS, a Lag that can be negative for lead, and a LagUnit choosing working days or raw calendar days.

Where did ViewMode go?

It was removed in 1.3.0 along with EnableToolbar. Zoom is now continuous through PixelsPerDay: roughly 40 is a week view, 12 a month and 4 a quarter, and omitting it auto-fits the data span. ZoomInAsync and ZoomOutAsync step it at runtime. Code written against 1.2.0 that sets ViewMode will not compile against 1.3.0.

Can I use custom HTML tooltips from Blazor?

Not currently. In the core the tooltip template is a JavaScript callback, and the Blazor wrapper serializes options as plain JSON with no mechanism for passing a function, so the template never runs. TooltipId sets the id of the tooltip container element, which is a different thing. EnableTooltip, TooltipBGColor and TooltipBorderColor all work.

Why does my Blazor Gantt chart render blank?

Usually the render mode. From .NET 8, Blazor Web Apps render statically by default, so a component that needs JavaScript interop must opt into InteractiveServer, InteractiveWebAssembly or InteractiveAuto. There is no error and nothing in the console when this is wrong. Also check that Height resolves to a real value.

Ready to schedule in C#?

One dotnet add package, one AddApexGantt, and an interactive render mode. ApexGantt needs a Premium license, and works watermarked while you evaluate it.

See ApexGantt features