Skip to main content

Filtering data

Filtering API

To filter tasks in Gantt, use the filter-tasks action. You can call it at any time via api.exec() and pass a function that receives each task and returns true (show) or false (hide).

The example below filters tasks by name as the user types:

<script>
import { Gantt } from "@svar-ui/svelte-gantt";
import { getData } from "./data";

const data = getData();
let api = $state();
let text = $state("");

function init(ganttApi) {
api = ganttApi;
}

$effect(() => {
if (api) api.exec("filter-tasks", {
filter: text
? (task) => (task.text || "").toLowerCase().includes(text.toLowerCase())
: null,
});
});
</script>

<input type="text" bind:value={text} placeholder="Filter by task name" />

<Gantt {init} tasks={data.tasks} links={data.links} scales={data.scales} />

To filter by multiple conditions at once, combine them inside a single function:

api.exec("filter-tasks", {
filter: (task) =>
task.duration > 5 &&
task.start >= new Date("2026-01-01"),
});

Embedding inline column filters

You can embed filter inputs directly into column headers by adding a filter object to a header cell configuration. When the user types or selects a value, the filter-tasks action fires automatically.

<script>
import { Gantt } from "@svar-ui/svelte-gantt";
import { getData } from "./data";

const data = getData();

const columns = [
{
id: "text",
header: ["Task name", { filter: { type: "text", config: { clear: true } } }],
width: 200,
},
{ id: "start", header: "Start date", width: 130 },
{ id: "duration", header: "Duration", width: 100 },
];
</script>

<Gantt
tasks={data.tasks}
links={data.links}
scales={data.scales}
{columns}
/>

The header property of the columns object accepts an array where each element maps to a header row. The first element is a plain string (the column title); the second element is an object with a filter key.

Integration with FilterBuilder

The FilterBuilder component allows users to build complex filter rules through a UI. You can connect it to Gantt so that tasks are filtered in real time as the user changes the filter conditions.

Integration steps

You need to have FilterBuilder installed: FilterBuilder installation.

1. Import the components and helpers

Import Gantt alongside FilterBuilder, getOptions, and createFilter from @svar-ui/svelte-filter.

import { Gantt } from "../../src/";
import { FilterBuilder, getOptions, createFilter } from "@svar-ui/svelte-filter";

2. Define the filterable fields

Create a fields array describing each column you want to expose in the filter UI. Each entry needs an id matching the task property, a label for display, and a type ("text", "date", or "number").

const fields = [
{ id: "text", label: "Task name", type: "text" },
{ id: "start", label: "Start date", type: "date" },
{ id: "end", label: "End date", type: "date" },
{ id: "duration", label: "Duration", type: "number" },
];

3. Build the options

Use getOptions(tasks, field) for each field to generate the list of available values from your task data. These populate the value dropdowns in the filter UI.

const options = {
text: getOptions(tasks, "text"),
start: getOptions(tasks, "start"),
end: getOptions(tasks, "end"),
duration: getOptions(tasks, "duration"),
};

4. Set an initial filter value

Define a value object with a glue ("and" / "or") and a rules array. Each rule specifies a field, a filter condition (e.g. "contains", "greater"), and a value. This is what FilterBuilder renders on load.

let value = {
glue: "or",
rules: [
{ field: "text", filter: "contains", value: "plan" },
{ field: "duration", filter: "greater", value: 5 },
],
};

5. Connect FilterBuilder to Gantt

In applyFilter, call createFilter(value) to convert the filter definition into a (task) => boolean function, then pass it to api.exec("filter-tasks", { filter }). Wire this to FilterBuilder's onchange so it runs every time the user edits a rule.

<script>
function applyFilter({ value }) {
const filter = createFilter(value);
api.exec("filter-tasks", { filter });
}
</script>

<FilterBuilder {value} {fields} {options} type="line" onchange={applyFilter} />

6. Apply the initial filter on mount

Use a $effect that watches the api reference. Once Gantt is ready, call applyFilter immediately so the chart opens in the pre-filtered state defined by your initial value.

$effect(() => {
if (api) applyFilter({ value });
});

Integration with FilterBuilder

Integration with FilterQuery

The FilterQuery component provides a single text input that accepts both structured query syntax and natural language. When the user types in natural language (e.g. "almost complete"), the component sends the text to an AI endpoint that converts it into a structured filter definition.

Integration steps

You need to have FilterQuery installed: FilterQuery installation.

1. Import the components and helpers

Import Gantt alongside FilterQuery, createFilter, getQueryString, and getOptionsMap from @svar-ui/svelte-filter.

import { Gantt } from "@svar-ui/svelte-gantt";
import { FilterQuery, createFilter, getQueryString, getOptionsMap } from "@svar-ui/svelte-filter";

2. Define the filterable fields

Create a fields array describing each task property you want the filter to work with. Each entry needs an id matching the task property, a label for display, and a type ("text", "date", or "number"). The fields list is also sent to the AI endpoint so it understands what properties are available.

const fields = [
{ id: "text", label: "Text", type: "text" },
{ id: "duration", label: "Duration", type: "number" },
{ id: "start", label: "Start Date", type: "date" },
{ id: "end", label: "End Date", type: "date" },
{ id: "progress", label: "Progress", type: "number" },
];

3. Build the options map

Use getOptionsMap(tasks) to generate a map of available values across all fields at once. This helps the component suggest valid values as the user types.

let options = getOptionsMap(tasks);

4. Set an initial query

Define a textValue string using query syntax. This is what FilterQuery renders on load and what gets updated when an AI response is parsed back into a query string.

let textValue = $state("Progress: < 20");

5. Connect FilterQuery to Gantt

Check whether the user submitted a natural language text string or a structured value. For natural language, forward the text to your AI endpoint (text2filter), then use getQueryString to reflect the parsed result back in the input. In both cases, call createFilter and apply the result via api.exec("filter-tasks", { filter }).

<script>
async function handleFilter({ value, error, text, startProgress, endProgress }) {
if (text) {
error = null;
try {
startProgress();
value = await text2filter(text, fields);
textValue = value ? getQueryString(value).query : "";
} catch (e) {
error = e;
} finally {
endProgress();
}
}

if (error) {
helpers.showNotice({ text: error.message, type: "danger" });
if (error.code !== "NO_DATA") return;
}

filter = createFilter(value, {}, fields);
}
</script>

<FilterQuery
value={textValue}
placeholder="e.g., Text: contains test or Duration: >5"
{fields}
{options}
onchange={handleFilter}
/>

6. Provide an AI text-to-filter endpoint

Implement a function that sends the user's natural language string along with the fields definition to an AI endpoint, and returns a structured filter object.

const AI_URL = "https://your-server.example.com/text-to-json";

async function text2filter(text, fields) {
const response = await fetch(AI_URL, {
method: "POST",
body: JSON.stringify({ text, fields }),
});
const json = await response.json();
if (!response.ok) throw new Error(json.error || "Request failed");
return json;
}

7. Apply the filter to Gantt

Use $effect that watches the filter state. Whenever it changes, the filter is applied to Gantt.

$effect(() => {
if (api && filter !== undefined) api.exec("filter-tasks", { filter });
});

Integration with FilterQuery