v7.3.0
SupportExamplesFree Trial

Interacting with the server

Now that we've reviewed the general concepts of working with data in Bryntum components, let's explore server interactions in more detail. There are multiple ways to interact with the server.

For Bryntum Gantt, you can either use loadUrl to interact with all stores collectively:

project : {
    loadUrl : '/data.php'
}

or use createUrl, readUrl, updateUrl, and deleteUrl to define an endpoint for each store individually. For example:

const gantt = new Gantt({
  // other config
  resourceStore : {
    createUrl : 'resource/create.js',
    readUrl   : 'resource/read.js',
    updateUrl : 'resource/update.js',
    deleteUrl : 'resource/delete.js'
  }
});
// GanttConfig.tsx
import { type BryntumGanttProps } from "@bryntum/gantt-react";

export const ganttProps: BryntumGanttProps = {
  // other config
  resourceStore : {
    createUrl : 'resource/create.js',
    readUrl   : 'resource/read.js',
    updateUrl : 'resource/update.js',
    deleteUrl : 'resource/delete.js'
  }
};
import ganttProps from "./ganttConfig";
// App.tsx
const App = props => {

    return <BryntumGantt {...ganttProps} />
}
<script setup lang="ts">
import { BryntumGantt } from '@bryntum/gantt-vue-3';
import ganttConfig  from './AppConfig.ts';
</script>

<template>
  <bryntum-gantt v-bind="ganttConfig" />
</template>
import { type BryntumGanttProps } from '@bryntum/gantt-vue-3';

export const ganttConfig : BryntumGanttProps = {
  // other config
  resourceStore : {
    createUrl : 'resource/create.js',
    readUrl   : 'resource/read.js',
    updateUrl : 'resource/update.js',
    deleteUrl : 'resource/delete.js'
  }
};
<bryntum-gantt
    #gantt
    [project]="ganttProps.project!"
></bryntum-gantt>
// app.config.ts
import { type BryntumGanttProps } from '@bryntum/gantt-angular';

export const ganttProps: BryntumGanttProps = {
  // other config
  resourceStore : {
    createUrl : 'resource/create.js',
    readUrl   : 'resource/read.js',
    updateUrl : 'resource/update.js',
    deleteUrl : 'resource/delete.js'
  }
};
// app.component.ts

export class AppComponent implements AfterViewInit {

    // other config
    ganttProps = ganttProps;
}
We don't recommend interacting with a store separately. The best is to use the Project for store interactions.

The ResourceStore then uses the URLs for AJAX requests for the different CRUD operations. You'll learn more about the ResourceStore in the store interaction section below.

The project is a top-level entity that holds multiple stores together.

You can pass autoLoad : true, if you want the data to be loaded automatically after a store has been initialized.

const gantt = new Gantt({
  // other config
  resourceStore : {
    autoLoad  : true,
    createUrl : 'resource/create.php',
    readUrl   : 'resource/read.php',
    updateUrl : 'resource/update.php',
    deleteUrl : 'resource/delete.php'
  }
});

Using Fetch

You can use the JavaScript Fetch API to fetch the data and feed it into the Bryntum Gantt:

const response = await fetch('resource/load.php');
const data = await response.json();

// feed it to Gantt like this:
const gantt = new Gantt({
    resourceStore : {
        data : data
    }
})

// or this:
gantt.resourceStore.data = data;

Understanding Project

The Project provides an easy way to define endpoints for server interactions. It accepts only two endpoints, one for loading data (loadUrl) and another for creating, updating, and deleting data (syncUrl).

const gantt = new Gantt({
  // other config
  project : {
    loadUrl : 'read.js',
    syncUrl : 'sync.js'
  },
})
// GanttConfig.tsx
import { type BryntumGanttProps } from "@bryntum/gantt-react";

export const ganttProps: BryntumGanttProps = {
  // other config
  project : {
    loadUrl : 'read.js',
    syncUrl : 'sync.js'
  }

};
import ganttProps from "./ganttConfig";
// App.tsx
const App = props => {

    return <BryntumGantt {...ganttProps} />
}
<script setup lang="ts">
import { BryntumGantt } from '@bryntum/gantt-vue-3';
import ganttConfig  from './AppConfig.ts';
</script>

<template>
  <bryntum-gantt v-bind="ganttConfig" />
</template>
import { type BryntumGanttProps } from '@bryntum/gantt-vue-3';

export const ganttConfig : BryntumGanttProps = {
    // other config
    project : {
      loadUrl : 'read.js',
      syncUrl : 'sync.js'
    }
};
<bryntum-gantt
    #gantt
    [project]="ganttProps.project!"
></bryntum-gantt>
// app.config.ts
import { type BryntumGanttProps } from '@bryntum/gantt-angular';

export const ganttProps: BryntumGanttProps = {
  // other config
  project : {
    loadUrl : 'read.js',
    syncUrl : 'sync.js'
  }
};
// app.component.ts

export class AppComponent implements AfterViewInit {

    // other config
    ganttProps = ganttProps;
}

Check out the Gantt demo that uses the Project.

The Bryntum component then uses the project to handle CRUD operations for you. Whenever changes are made to tasks, assignments, resources, or anything else, a request is sent to the syncUrl path.

On the backend, you can see the type of change (Create, Update, or Delete) by looking at the request body. Then, based on the operation type, it sends the relevant data.

The following examples use the loadUrl to load the Gantt data with a fake API call using project.

const gantt = new Gantt({ appendTo : targetElement, height : 400, project : { autoLoad : true, loadUrl : '/mockUrl' }, columns : [ { type : 'name', width : 250 } ] }); // AJAX URL Mocking AjaxHelper.mockUrl('/mockUrl', (url, params) => { return { responseText : JSON.stringify(ganttData()) }; }); function ganttData() { return { success : true, project : { calendar : 'general' }, calendars : { rows : [ { id : 'general', name : 'General', intervals : [ { recurrentStartDate : 'on Sat at 0:00', recurrentEndDate : 'on Mon at 0:00', isWorking : false } ], expanded : true, children : [ { id : 'business', name : 'Business', hoursPerDay : 8, daysPerWeek : 5, daysPerMonth : 20, intervals : [ { recurrentStartDate : 'every weekday at 12:00', recurrentEndDate : 'every weekday at 13:00', isWorking : false }, { recurrentStartDate : 'every weekday at 17:00', recurrentEndDate : 'every weekday at 08:00', isWorking : false } ] }, { id : 'night', name : 'Night shift', hoursPerDay : 8, daysPerWeek : 5, daysPerMonth : 20, intervals : [ { recurrentStartDate : 'every weekday at 6:00', recurrentEndDate : 'every weekday at 22:00', isWorking : false } ] } ] } ] }, tasks : { rows : [ { id : 1000, startDate : '2017-01-16', name : 'Project A', percentDone : 43, expanded : true, children : [ { id : 1, name : 'Planning', percentDone : 60, startDate : '2017-01-16', duration : 10, expanded : true, rollup : true, children : [ { id : 11, name : 'Investigate', percentDone : 70, startDate : '2017-01-16', duration : 10 }, { id : 12, name : 'Assign resources', percentDone : 60, startDate : '2017-01-16', duration : 8 }, { id : 13, name : 'Gather documents', percentDone : 50, startDate : '2017-01-16', duration : 8 }, { id : 14, name : 'Report to management', percentDone : 0, startDate : '2017-01-28', duration : 0 } ] }, { id : 2, name : 'Implementation Phase', percentDone : 20, startDate : '2017-01-30', duration : 10, expanded : true, rollup : true, children : [ { id : 21, name : 'Preparation work', percentDone : 40, startDate : '2017-01-30', duration : 5 }, { id : 22, name : 'Choose technology suite', percentDone : 30, startDate : '2017-01-30', duration : 4, rollup : true }, { id : 23, name : 'Build prototype', percentDone : 9, startDate : '2017-02-06', duration : 5, expanded : true, children : [ { id : 231, name : 'Step 1', percentDone : 20, startDate : '2017-02-06', duration : 4 }, { id : 232, name : 'Step 2', percentDone : 10, startDate : '2017-02-06', duration : 4 }, { id : 233, name : 'Step 3', percentDone : 0, startDate : '2017-02-06', duration : 4 }, { id : 234, name : 'Follow up with customer', percentDone : 0, startDate : '2017-02-10', duration : 1, rollup : true } ] } ] }, { id : 3, name : 'Customer approval', percentDone : 0, startDate : '2017-02-13', duration : 0, rollup : true } ] } ] }, dependencies : { rows : [ { id : 1, fromEvent : 11, toEvent : 14 }, { id : 2, fromEvent : 12, toEvent : 14 }, { id : 3, fromEvent : 13, toEvent : 14 }, { id : 4, fromEvent : 14, toEvent : 21 }, { id : 5, fromEvent : 14, toEvent : 22 }, { id : 6, fromEvent : 22, toEvent : 231 }, { id : 7, fromEvent : 22, toEvent : 232 }, { id : 8, fromEvent : 22, toEvent : 233 }, { id : 9, fromEvent : 233, toEvent : 234 }, { id : 10, fromEvent : 234, toEvent : 3 } ] }, resources : { rows : [ { id : 1, name : 'Celia', city : 'Barcelona' }, { id : 2, name : 'Lee', city : 'London' }, { id : 3, name : 'Macy', city : 'New York' }, { id : 4, name : 'Madison', city : 'Barcelona' }, { id : 5, name : 'Rob', city : 'Rome' }, { id : 6, name : 'Dave', city : 'Barcelona' }, { id : 7, name : 'Dan', city : 'London' }, { id : 8, name : 'George', city : 'New York' }, { id : 9, name : 'Gloria', city : 'Rome' }, { id : 10, name : 'Henrik', city : 'London', calendar : 'business' } ] }, assignments : { rows : [ { event : 11, resource : 1 }, { event : 12, resource : 1 }, { event : 12, resource : 9 }, { event : 13, resource : 2 }, { event : 13, resource : 3 }, { event : 13, resource : 6 }, { event : 13, resource : 7 }, { event : 13, resource : 8 }, { event : 21, resource : 5 }, { event : 21, resource : 9 }, { event : 22, resource : 8 }, { event : 234, resource : 3 } ] } }; }

Store interactions

You can use one of the stores, such as AssignmentStore or ResourceStore, to handle a specific type of store data. For example:

const customAssignmentStore = new AssignmentStore({
  createUrl : "assignment/create.php",
  readUrl   : "assignment/read.php",
  updateUrl : "assignment/update.php",
  deleteUrl : "assignment/delete.php"
});

new Gantt({
  assignmentStore : customAssignmentStore
})

We recommend you use this approach when you have API endpoints for a specific store, like AssignmentStore. The Bryntum Gantt will then use these endpoints to interact with the server for assignment-related data.

This means you can have multiple data-specific stores:

new Gantt({
  assignmentStore : {
      createUrl : "assignment/create.php",
      readUrl   : "assignment/read.php",
      updateUrl : "assignment/update.php",
      deleteUrl : "assignment/delete.php"
  },
  resourceStore   : {
    createUrl : "resource/create.php",
    readUrl   : "resource/read.php",
    updateUrl : "resource/update.php",
    deleteUrl : "resource/delete.php"
  }
});

This is useful for managing a single store, but management becomes more difficult when you use all your stores this way. Therefore, we encourage you to use the Project to manage your data.

Headers

You can use the headers config to configure requests and send custom HTTP headers to the server:

project : {
  transport : {
    sync : {
        url : 'http://mycool-server.com/sync.php',
        // specify Content-Type for requests
        headers : {
            'Content-Type' : 'application/json'
        }
    }
  }
}

If you want send headers in a separate store :

// Configuring headers for each request
const resourceStore = new ResourceStore({
  readUrl : "resource/read.php",
  headers : {
    "Content-Type"   : "text/xml",
    "Accept-Charset" : "utf-8",
  },
});

Next, let's learn how data is structured for different requests.

Continue reading: Understanding structure.

Contents