---
title: "Time Series"
enterprise: true
framework: vue
version: "36.1.0"
---

# Time Series

This section covers how to chart time series data using Integrated Charts.

Integrated Charts supports the charting of time series data using line and area charts when a time axis is chosen instead of a category or numeric axis.

## Time vs Category Axis

A [Time Axis](https://www.ag-grid.com/charts/react/axes-types/#time) is used to plot continuous date / time values, whereas a [Category Axis](https://www.ag-grid.com/charts/react/axes-types/#category) is used to plot discrete values or categories.

The example below highlights the differences between time and category axes. Notice that the time axis contains all days for the range of values provided, whereas the category axis only shows axis labels for the discrete values provide.

#### Time vs Category Axis

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./style.css";
import { AgChartsEnterpriseModule } from "ag-charts-enterprise";
import {
  AgChartThemeOverrides,
  CellSelectionOptions,
  ChartToolPanelsDef,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  ColumnApiModule,
  FirstDataRenderedEvent,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  ValueFormatterParams,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  IntegratedChartsModule,
  RowGroupingModule,
} from "ag-grid-enterprise";
import { getData } from "./data";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ColumnApiModule,
  ClientSideRowModelModule,
  IntegratedChartsModule.with(AgChartsEnterpriseModule),
  ColumnMenuModule,
  ContextMenuModule,
  RowGroupingModule,
]);

let currentChartRef: any;

function getColumnDefs() {
  return [
    { field: "date", valueFormatter: dateFormatter },
    { field: "avgTemp" },
  ];
}

function dateFormatter(params: ValueFormatterParams) {
  return params.value
    ? params.value.toISOString().substring(0, 10)
    : params.value;
}

function formatDate(date: Date | number) {
  return Intl.DateTimeFormat("en-GB", {
    day: "2-digit",
    month: "short",
    year: undefined,
  }).format(new Date(date));
}

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div class="wrapper">
      <div id="buttonRow">
        <label>Switch Axis to: </label>
        <button id="axisBtn" v-on:click="toggleAxis()" value="time">Category</button>
      </div>
      <ag-grid-vue
        style="width: 100%; height: 100%;"
        class="my-grid"
        @grid-ready="onGridReady"
        :columnDefs="columnDefs"
        :defaultColDef="defaultColDef"
        :cellSelection="true"
        :popupParent="popupParent"
        :enableCharts="true"
        :chartThemeOverrides="chartThemeOverrides"
        :chartToolPanelsDef="chartToolPanelsDef"
        :rowData="rowData"
        @first-data-rendered="onFirstDataRendered"></ag-grid-vue>
        <div id="myChart" class="my-chart"></div>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi | null>(null);
    const columnDefs = ref<ColDef[]>(getColumnDefs());
    const defaultColDef = ref<ColDef>({ flex: 1 });
    const popupParent = ref<HTMLElement | null>(document.body);
    const chartThemeOverrides = ref<AgChartThemeOverrides>({
      line: {
        title: {
          enabled: true,
          text: "Average Daily Temperatures",
        },
        navigator: {
          enabled: true,
          height: 20,
          spacing: 25,
        },
        axes: {
          time: {
            label: {
              rotation: 0,
              format: "%d %b",
            },
          },
          category: {
            label: {
              rotation: 0,
              formatter: (params: any) => {
                // charts typings
                return formatDate(params.value);
              },
            },
          },
          number: {
            label: {
              formatter: (params: any) => {
                // charts typings
                return params.value + "°C";
              },
            },
          },
        },
      },
    });
    const chartToolPanelsDef = ref<ChartToolPanelsDef>({
      panels: ["data", "format"],
    });
    const rowData = ref<any[]>(null);

    function onFirstDataRendered(params: FirstDataRenderedEvent) {
      if (currentChartRef) {
        currentChartRef.destroyChart();
      }
      currentChartRef = params.api.createRangeChart({
        chartContainer: document.querySelector("#myChart") as HTMLElement,
        cellRange: {
          columns: ["date", "avgTemp"],
        },
        suppressChartRanges: true,
        chartType: "line",
      });
    }
    function toggleAxis() {
      const axisBtn = document.querySelector("#axisBtn") as any;
      axisBtn.textContent = axisBtn.value;
      axisBtn.value = axisBtn.value === "time" ? "category" : "time";
      const columnDefs: ColDef[] = getColumnDefs();
      columnDefs.forEach((colDef) => {
        if (colDef.field === "date") {
          colDef.chartDataType = axisBtn.value;
        }
      });
      gridApi.value!.setGridOption("columnDefs", columnDefs);
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      getData().then((rowData) => params.api.setGridOption("rowData", rowData));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      popupParent,
      chartThemeOverrides,
      chartToolPanelsDef,
      rowData,
      onGridReady,
      onFirstDataRendered,
      toggleAxis,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Time vs Category Axis](https://www.ag-grid.com/examples/integrated-charts-time-series/time-vs-category/vue3)

## Time Axis Configuration

A [Time Axis](https://www.ag-grid.com/charts/react/axes-types/#time) can be configured by setting `chartDataType = 'time'` on the column definition.

For the time axis to work correctly, the column must contain values in one of the following formats:

- `Date`
- `string` in ISO 8601 format
- `number` representing the numeric timestamp

Additionally, if `chartDataType` is not specified and the column contains `Date` values, it will automatically use a time axis.

The following snippet shows how different time series values can be configured to enable a time axis:

```ts
<ag-grid-vue
    :columnDefs="columnDefs"
    :rowData="rowData"
    /* other grid options ... */>
</ag-grid-vue>

this.columnDefs = [
    // date objects are treated as time by default
    { field: 'someDate' },
    { field: 'someIsoString', chartDataType: 'time' },
    { field: 'someTimestamp', chartDataType: 'time' },
];
this.rowData = [
    {
        someDate: new Date('Mon Apr 17 2023 12:43:17'), // date object
        someIsoString: '2023-04-17T11:43:17.000Z', // ISO 8601 string
        someTimestamp: 1681735397000, // numeric timestamp (JavaScript format)
    },
    // ... more rows
];
```

The following example demonstrates configuring numeric timestamps to use a time axis:

#### Time Axis Configuration

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./style.css";
import { AgChartsEnterpriseModule } from "ag-charts-enterprise";
import {
  AgChartThemeOverrides,
  CellSelectionOptions,
  ChartToolPanelsDef,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  FirstDataRenderedEvent,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  IntegratedChartsModule,
  RowGroupingModule,
} from "ag-grid-enterprise";
import { getData } from "./data";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  IntegratedChartsModule.with(AgChartsEnterpriseModule),
  ColumnMenuModule,
  ContextMenuModule,
  RowGroupingModule,
]);

function formatTime(date: Date | number) {
  return Intl.DateTimeFormat("en-GB", {
    hour: "2-digit",
    minute: "2-digit",
    second: "2-digit",
  }).format(new Date(date));
}

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div class="wrapper">
      <ag-grid-vue
        style="width: 100%; height: 100%;"
        class="my-grid"
        @grid-ready="onGridReady"
        :columnDefs="columnDefs"
        :defaultColDef="defaultColDef"
        :cellSelection="true"
        :popupParent="popupParent"
        :enableCharts="true"
        :chartThemeOverrides="chartThemeOverrides"
        :chartToolPanelsDef="chartToolPanelsDef"
        :rowData="rowData"
        @first-data-rendered="onFirstDataRendered"></ag-grid-vue>
        <div id="myChart" class="my-chart"></div>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "timestamp", chartDataType: "time" },
      { field: "cpuUsage" },
    ]);
    const defaultColDef = ref<ColDef>({ flex: 1 });
    const popupParent = ref<HTMLElement | null>(document.body);
    const chartThemeOverrides = ref<AgChartThemeOverrides>({
      area: {
        title: {
          enabled: true,
          text: "CPU Usage",
        },
        navigator: {
          enabled: true,
          height: 20,
          spacing: 25,
        },
        axes: {
          time: {
            label: {
              rotation: 315,
              format: "%H:%M",
            },
          },
          number: {
            label: {
              formatter: (params: any) => {
                // charts typings
                return params.value + "%";
              },
            },
          },
        },
      },
    });
    const chartToolPanelsDef = ref<ChartToolPanelsDef>({
      panels: ["data", "format"],
    });
    const rowData = ref<any[]>(null);

    function onFirstDataRendered(params: FirstDataRenderedEvent) {
      params.api.createRangeChart({
        chartContainer: document.querySelector("#myChart") as HTMLElement,
        cellRange: {
          columns: ["timestamp", "cpuUsage"],
        },
        suppressChartRanges: true,
        chartType: "area",
      });
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      getData().then((rowData) => params.api.setGridOption("rowData", rowData));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      popupParent,
      chartThemeOverrides,
      chartToolPanelsDef,
      rowData,
      onGridReady,
      onFirstDataRendered,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Time Axis Configuration](https://www.ag-grid.com/examples/integrated-charts-time-series/time-axis-config/vue3)

## Time Axis Combination Chart

A time axis can also be used in combination charts as shown in the following example.

For more details on how to configure a combination chart, see the [Range Chart API example](https://www.ag-grid.com/vue-data-grid/integrated-charts-api-range-chart/#combination-charts).

#### Time Axis Combination Chart

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./style.css";
import { AgChartsEnterpriseModule } from "ag-charts-enterprise";
import {
  AgAxisCaptionFormatterParams,
  AgCartesianSeriesTooltipRendererParams,
  AgCrosshairLabelRendererParams,
} from "ag-charts-types";
import {
  AgChartThemeOverrides,
  CellSelectionOptions,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  FirstDataRenderedEvent,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  ValueParserParams,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  IntegratedChartsModule,
  RowGroupingModule,
} from "ag-grid-enterprise";
import { getData } from "./data";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  IntegratedChartsModule.with(AgChartsEnterpriseModule),
  ColumnMenuModule,
  ContextMenuModule,
  RowGroupingModule,
]);

function numberParser(params: ValueParserParams) {
  const value = params.newValue;
  if (value === null || value === undefined || value === "") {
    return null;
  }
  return parseFloat(value);
}

function formatDate(date: Date | number) {
  return Intl.DateTimeFormat("en-GB", {
    day: "2-digit",
    month: "short",
    year: undefined,
  }).format(new Date(date));
}

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div class="wrapper">
      <ag-grid-vue
        style="width: 100%; height: 100%;"
        @grid-ready="onGridReady"
        :columnDefs="columnDefs"
        :defaultColDef="defaultColDef"
        :cellSelection="true"
        :popupParent="popupParent"
        :enableCharts="true"
        :chartThemeOverrides="chartThemeOverrides"
        :rowData="rowData"
        @first-data-rendered="onFirstDataRendered"></ag-grid-vue>
        <div id="myChart"></div>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi | null>(null);
    const columnDefs = ref<ColDef[]>([
      {
        field: "date",
        chartDataType: "time",
        valueFormatter: (params) => params.value.toISOString().substring(0, 10),
      },
      { field: "rain", chartDataType: "series", valueParser: numberParser },
      { field: "pressure", chartDataType: "series", valueParser: numberParser },
      { field: "temp", chartDataType: "series", valueParser: numberParser },
    ]);
    const defaultColDef = ref<ColDef>({ flex: 1 });
    const popupParent = ref<HTMLElement | null>(document.body);
    const chartThemeOverrides = ref<AgChartThemeOverrides>({
      common: {
        padding: {
          top: 45,
        },
        axes: {
          number: {
            title: {
              enabled: true,
              formatter: (params: AgAxisCaptionFormatterParams) => {
                return params.boundSeries.map((s) => s.name).join(" / ");
              },
            },
          },
          time: {
            crosshair: {
              label: {
                renderer: (params: AgCrosshairLabelRendererParams) => ({
                  text: formatDate(params.value),
                }),
              },
            },
          },
        },
      },
      bar: {
        series: {
          strokeWidth: 2,
          fillOpacity: 0.8,
        },
      },
      line: {
        series: {
          strokeWidth: 5,
          strokeOpacity: 0.8,
        },
      },
    });
    const rowData = ref<any[]>(null);

    function onFirstDataRendered(params: FirstDataRenderedEvent) {
      params.api.createRangeChart({
        chartContainer: document.querySelector("#myChart") as HTMLElement,
        cellRange: {
          columns: ["date", "rain", "pressure", "temp"],
        },
        suppressChartRanges: true,
        seriesChartTypes: [
          { colId: "rain", chartType: "groupedColumn", secondaryAxis: false },
          { colId: "pressure", chartType: "line", secondaryAxis: true },
          { colId: "temp", chartType: "line", secondaryAxis: true },
        ],
        chartType: "customCombo",
        aggFunc: "sum",
      });
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      getData().then((rowData) => params.api.setGridOption("rowData", rowData));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      popupParent,
      chartThemeOverrides,
      rowData,
      onGridReady,
      onFirstDataRendered,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Time Axis Combination Chart](https://www.ag-grid.com/examples/integrated-charts-time-series/time-combination-chart/vue3)
