Column Pinning (Frozen) in Vue Gantt Chart Component

18 Nov 201824 minutes to read

The Vue Gantt Chart component provides a frozen columns feature that keeps selected columns fixed while scrolling horizontally through large datasets. This functionality ensures that critical information remains visible at all times, improving readability and user experience. By maintaining key columns in view, it simplifies navigation and makes referencing important data points easier when working with extensive project details.

To enable frozen columns, use the frozenColumns property in the Gantt Chart component.

In the following example, the frozenColumns property is set to 2, which keeps the first two columns fixed on the left while the remaining columns can be scrolled horizontally.

<template>
  <div>
    <ejs-gantt
      id="GanttContainer"
      :dataSource="data"
      :taskFields="taskFields"
      :height="height"
      :gridLines="gridLines"
      :splitterSettings="splitterSettings"
      :labelSettings="labelSettings"
      :columns="columns"
      :frozenColumns="frozenColumns"
      :treeColumnIndex="treeColumnIndex"
      :allowSelection="allowSelection"
    ></ejs-gantt>
  </div>
</template>

<script setup>
import { GanttComponent as EjsGantt } from "@syncfusion/ej2-vue-gantt";
import { GanttData } from "./data-source.js";

const data = GanttData;
const height = "450px";

const columns = [
  { field: "TaskID", headerText: "Task ID", textAlign: "Right", width: 90 },
  { field: "TaskName", headerText: "Task Name", textAlign: "Left", width: 290 },
  { field: "StartDate", headerText: "Start Date", textAlign: "Right", width: 120, format: "yMd" },
  { field: "Duration", headerText: "Duration", textAlign: "Right", width: 90 },
  { field: "EndDate", headerText: "End Date", textAlign: "Right", width: 120, format: "yMd" },
  { field: "Progress", headerText: "Progress", textAlign: "Left", width: 120 },
  { field: "Predecessor", headerText: "Predecessor", textAlign: "Left", width: 120 }
];

const taskFields = {
  id: "TaskID",
  name: "TaskName",
  startDate: "StartDate",
  endDate: "EndDate",
  duration: "Duration",
  dependency: "Predecessor",
  progress: "Progress",
  parentID: "ParentID"
};

const labelSettings = { taskLabel: "Progress" };
const splitterSettings = { position: "65%" };
const gridLines = "Both";
const frozenColumns = 2;
const treeColumnIndex = 1;
const allowSelection = false;
</script>
<template>
  <div>
    <ejs-gantt
      ref="gantt"
      id="GanttContainer"
      :dataSource="data"
      :taskFields="taskFields"
      :height="height"
      :gridLines="gridLines"
      :splitterSettings="splitterSettings"
      :labelSettings="labelSettings"
      :columns="columns"
      :frozenColumns="frozenColumns"
      :treeColumnIndex="treeColumnIndex"
      :allowSelection="allowSelection"
    >
    </ejs-gantt>
  </div>
</template>
<script>
import { GanttComponent } from "@syncfusion/ej2-vue-gantt";
import { GanttData } from "./data-source.js";
export default {
  name: "App",
  components: {
    "ejs-gantt": GanttComponent,
  },
  data: function () {
    return {
      data: GanttData,
      height: "450px",
      columns: [
        {
          field: "TaskID",
          headerText: "Task ID",
          textAlign: "Right",
          width: 90,
        },
        {
          field: "TaskName",
          headerText: "Task Name",
          textAlign: "Left",
          width: 290,
        },
        {
          field: "StartDate",
          headerText: "Start Date",
          textAlign: "Right",
          width: 120,
          format: "yMd",
        },
        {
          field: "Duration",
          headerText: "Duration",
          textAlign: "Right",
          width: 90,
        },
        {
          field: "EndDate",
          headerText: "End Date",
          textAlign: "Right",
          width: 120,
          format: "yMd",
        },
        {
          field: "Progress",
          headerText: "Progress",
          textAlign: "Left",
          width: 120,
        },
        {
          field: "Predecessor",
          headerText: "Predecessor",
          textAlign: "Left",
          width: 120,
        },
      ],
      taskFields: {
        id: "TaskID",
        name: "TaskName",
        startDate: "StartDate",
        duration: "Duration",
        progress: "Progress",
        parentID: "ParentID",
        endDate: "EndDate",
        dependency: "Predecessor",
      },
      labelSettings: {
        taskLabel: "Progress",
      },
      splitterSettings: {
        position: "65%",
      },
      gridLines: "Both",
      frozenColumns: 2,
      treeColumnIndex: 1,
      allowSelection: false,
    };
  },
  provide: {
    gantt: [],
  },
};
</script>

Freeze particular columns

The Vue Gantt provides a feature that enables freezing specific columns, significantly enhancing data visibility and improving the user experience. The isFrozen property is used at the column level to freeze a specific column at any desired index on the left side, offering flexibility in managing which columns are frozen.

To freeze a particular column in the Gantt, set the isFrozen property of the column to true.

The following example demonstrates how to freeze a particular column in the Gantt using the isFrozen property.

<template>
  <div>
    <ejs-gantt
      id="GanttContainer"
      :dataSource="data"
      :taskFields="taskFields"
      :height="height"
      :treeColumnIndex="treeColumnIndex"
      :splitterSettings="splitterSettings"
      :gridLines="gridLines"
      :labelSettings="labelSettings"
      :columns="columns"
    ></ejs-gantt>
  </div>
</template>

<script setup>
import { GanttComponent as EjsGantt } from "@syncfusion/ej2-vue-gantt";
import { GanttData } from "./data-source.js";

const data = GanttData;
const height = "430px";
const treeColumnIndex = 1;
const gridLines = "Both";

const taskFields = {
  id: 'TaskID',
  name: 'TaskName',
  startDate: 'StartDate',
  duration: 'Duration',
  endDate: 'EndDate',
  progress: 'Progress',
  parentID: 'ParentID',
};

const splitterSettings = { position: "65%" };
const labelSettings = { taskLabel: "Progress" };

const columns = [
  { field: 'TaskID', headerText: 'Task ID', isFrozen: true },
  { field: 'TaskName', headerText: 'Task Name', width: 220, isFrozen: true },
  { field: 'StartDate', headerText: 'Start Date' },
  { field: 'Duration', headerText: 'Duration' },
  { field: 'Progress', headerText: 'Progress' },
  { field: 'Status', headerText: 'Status', isFrozen: true }
];
</script>
<template>
  <div>
    <ejs-gantt
      id="GanttContainer"
      :dataSource="data"
      :taskFields="taskFields"
      :height="height"
      :treeColumnIndex="treeColumnIndex"
      :splitterSettings="splitterSettings"
      :gridLines="gridLines"
      :labelSettings="labelSettings"
      :columns="columns"
    ></ejs-gantt>
  </div>
</template>

<script>
import { GanttComponent } from "@syncfusion/ej2-vue-gantt";
import { GanttData } from "./data-source.js";

export default {
  name: "App",
  components: {
    "ejs-gantt": GanttComponent,
  },
  data() {
    return {
      data: GanttData,
      height: "430px",
      treeColumnIndex: 1,
      gridLines: "Both",
      taskFields: {
        id: 'TaskID',
        name: 'TaskName',
        startDate: 'StartDate',
        duration: 'Duration',
        endDate: 'EndDate',
        progress: 'Progress',
        parentID: 'ParentID',
      },
      splitterSettings: { position: "65%" },
      labelSettings: { taskLabel: "Progress" },
      columns: [
        { field: 'TaskID', headerText: 'Task ID', isFrozen: true },
        { field: 'TaskName', headerText: 'Task Name', width: 220, isFrozen: true },
        { field: 'StartDate', headerText: 'Start Date' },
        { field: 'Duration', headerText: 'Duration' },
        { field: 'Progress', headerText: 'Progress' },
        { field: 'Status', headerText: 'Status', isFrozen: true }
      ],
    };
  },
  provide: {
    gantt: [],
  },
};
</script>

Freeze direction

In the Vue Gantt, the freeze direction feature allows you to position frozen columns either to the left, right, or in a fixed position, while still allowing the remaining columns to be horizontally movable.

To achieve this, the column.freeze property can be utilized. This property is used to specify the freeze direction for individual columns.

The types of the column.freeze directions:

  • Left: When the column.freeze property is set to Left, specific columns will be frozen on the left side.

  • Right: When the column.freeze property is set to Right, certain columns will be frozen on the right side.

  • Fixed: The Fixed direction locks a column at a fixed position within the Gantt columns. This ensures that the column is always visible during horizontal scroll.

In the following example, the TaskID column is frozen on the left side, the resources column is frozen on the right side and the Progress column is frozen on the fixed of the content table.

<template>
  <div>
    <ejs-gantt
      id="GanttContainer"
      :dataSource="data"
      :taskFields="taskFields"
      :height="height"
      :treeColumnIndex="treeColumnIndex"
      :splitterSettings="splitterSettings"
      :gridLines="gridLines"
      :resources="resources"
      :resourceFields="resourceFields"
      :labelSettings="labelSettings"
      :columns="columns"
    ></ejs-gantt>
  </div>
</template>

<script setup>
import { GanttComponent as EjsGantt } from "@syncfusion/ej2-vue-gantt";
import { GanttData, resourceCollection } from "./data-source.js";

const data = GanttData;
const height = "430px";
const treeColumnIndex = 1;
const gridLines = "Both";

const taskFields = {
  id: "TaskID",
  name: "TaskName",
  startDate: "StartDate",
  endDate: "EndDate",
  duration: "Duration",
  dependency: "Predecessor",
  progress: "Progress",
  parentID: "ParentID",
  resourceInfo: "Resources"
};

const splitterSettings = { position: "65%" };
const labelSettings = { taskLabel: "Progress" };

const resources = resourceCollection;
const resourceFields = {
  id: "resourceId",
  name: "resourceName"
};

const columns = [
  { field: "TaskID", headerText: "Task ID", freeze: "Left" },
  { field: "TaskName", headerText: "Task Name", width: 200 },
  { field: "StartDate", headerText: "Start Date", width: 130 },
  { field: "Duration", headerText: "Duration", width: 110 },
  { field: "EndDate", headerText: "End Date", width: 130 },
  { field: "Progress", headerText: "Progress", width: 110, freeze: "Fixed" },
  { field: "Predecessor", headerText: "Dependency", width: 120 },
  { field: "Resources", headerText: "Assignee", freeze: "Right" }
];
</script>
<template>
  <div>
    <ejs-gantt
      id="GanttContainer"
      :dataSource="data"
      :taskFields="taskFields"
      :height="height"
      :treeColumnIndex="treeColumnIndex"
      :splitterSettings="splitterSettings"
      :gridLines="gridLines"
      :resources="resources"
      :resourceFields="resourceFields"
      :labelSettings="labelSettings"
      :columns="columns"
    ></ejs-gantt>
  </div>
</template>

<script>
import { GanttComponent } from "@syncfusion/ej2-vue-gantt";
import { GanttData, resourceCollection } from "./data-source.js";

export default {
  name: "App",
  components: {
    "ejs-gantt": GanttComponent,
  },
  data() {
    return {
      height: "430px",
      data: GanttData,
      treeColumnIndex: 1,
      gridLines: "Both",
      taskFields: {
        id: "TaskID",
        name: "TaskName",
        startDate: "StartDate",
        endDate: "EndDate",
        duration: "Duration",
        dependency: "Predecessor",
        progress: "Progress",
        parentID: "ParentID",
        resourceInfo: "Resources",
      },
      splitterSettings: { position: "65%" },
      labelSettings: { taskLabel: "Progress" },
      resources: resourceCollection,
      resourceFields: {
        id: "resourceId",
        name: "resourceName",
      },
      columns: [
        { field: "TaskID", headerText: "Task ID", freeze: "Left" },
        { field: "TaskName", headerText: "Task Name", width: 200 },
        { field: "StartDate", headerText: "Start Date", width: 130 },
        { field: "Duration", headerText: "Duration", width: 110 },
        { field: "EndDate", headerText: "End Date", width: 130 },
        { field: "Progress", headerText: "Progress", width: 110, freeze: "Fixed" },
        { field: "Predecessor", headerText: "Dependency", width: 120 },
        { field: "Resources", headerText: "Assignee", freeze: "Right" },
      ],
    };
  },
  provide: {
    gantt: [],
  },
};
</script>

Change default frozen line color

The frozen line borders of frozen columns in the Vue Gantt Chart component can be customized by applying custom CSS styles to the respective frozen columns. This allows you to change the border color of left, right, and fixed frozen columns to match your application’s design and theme.

To change the default frozen line color, use the following CSS class names and apply the desired border color:

For left frozen columns:

.e-gantt .e-leftfreeze.e-freezeleftborder {
    border-right-color: rgb(0, 255, 0) !important;
}

For right frozen columns:

.e-gantt .e-rightfreeze.e-freezerightborder {
    border-left-color: rgb(0, 0, 255) !important;
}

For fixed frozen columns, both left and right borders need to be specified as mentioned below:

.e-gantt .e-leftfreeze.e-freezeleftborder {
    border-right-color: rgb(0, 255, 0) !important;
}

.e-gantt .e-rightfreeze.e-freezerightborder {
    border-left-color: rgb(0, 0, 255) !important;
}

The following example demonstrates how to change the default frozen line color using CSS:

<template>
  <div>
    <ejs-gantt
      id="GanttContainer"
      :dataSource="data"
      :taskFields="taskFields"
      :height="height"
      :treeColumnIndex="treeColumnIndex"
      :splitterSettings="splitterSettings"
      :allowSelection="allowSelection"
      :gridLines="gridLines"
      :columns="columns"
    ></ejs-gantt>
  </div>
</template>

<script setup>
import { GanttComponent as EjsGantt } from "@syncfusion/ej2-vue-gantt";
import { GanttData } from "./data-source.js";

const data = GanttData;
const height = "430px";
const treeColumnIndex = 1;
const allowSelection = false;
const gridLines = "Both";

const taskFields = {
  id: "TaskID",
  name: "TaskName",
  startDate: "StartDate",
  endDate: "EndDate",
  duration: "Duration",
  dependency: "Predecessor",
  progress: "Progress",
  parentID: "ParentID"
};

const splitterSettings = { position: "65%" };

const columns = [
  { field: "TaskID", headerText: "Task ID", freeze: "Left" },
  { field: "TaskName", headerText: "Task Name", width: 200, freeze: "Left" },
  { field: "StartDate", headerText: "Start Date" },
  { field: "Duration", headerText: "Duration" },
  { field: "EndDate", headerText: "End Date" },
  { field: "Progress", headerText: "Progress", freeze: "Right" },
  { field: "Status", headerText: "Status" }
];
</script>
<template>
  <div>
    <ejs-gantt
      id="GanttContainer"
      :dataSource="data"
      :taskFields="taskFields"
      :height="height"
      :treeColumnIndex="treeColumnIndex"
      :splitterSettings="splitterSettings"
      :allowSelection="allowSelection"
      :gridLines="gridLines"
      :columns="columns"
    ></ejs-gantt>
  </div>
</template>

<script>
import { GanttComponent } from "@syncfusion/ej2-vue-gantt";
import { GanttData } from "./data-source.js";

export default {
  name: "App",
  components: {
    "ejs-gantt": GanttComponent,
  },
  data() {
    return {
      height: "430px",
      data: GanttData,
      treeColumnIndex: 1,
      allowSelection: false,
      gridLines: "Both",
      taskFields: {
        id: "TaskID",
        name: "TaskName",
        startDate: "StartDate",
        endDate: "EndDate",
        duration: "Duration",
        dependency: "Predecessor",
        progress: "Progress",
        parentID: "ParentID",
      },
      splitterSettings: { position: "65%" },
      columns: [
        { field: "TaskID", headerText: "Task ID", freeze: "Left" },
        { field: "TaskName", headerText: "Task Name", width: 200, freeze: "Left" },
        { field: "StartDate", headerText: "Start Date" },
        { field: "Duration", headerText: "Duration" },
        { field: "EndDate", headerText: "End Date" },
        { field: "Progress", headerText: "Progress", freeze: "Right" },
        { field: "Status", headerText: "Status" },
      ],
    };
  },
  provide: {
    gantt: [],
  },
};
</script>

Limitations