# Compose SDK Charts
The chart components found in the sdk-ui
modules of Compose SDK are a great way to display analytics data with minimal effort. They can be used out of the box with data retrieved from a Sisense instance, or with the correct structure, data retrieved from anywhere else.
The charts allow you to customize the data that is presented, how that data is styled, and how your users can interact with that data. The components provide properties for the most common customization options and also allow you to manipulate the underlying chart configuration before rendering if necessary.
Compose SDK charts are currently available as React and Angular components.
There are several different types of components you can use to display charts.
- Specific chart components - Each chart type has a component specifically for that chart type. For example, to display a pie chart, you can use the
<PieChart />
component. These components offer the most granular customization levels since their properties are tailored to the specific type of chart you’re working with. - Chart - A universal
<Chart />
component that can be used to display charts of different types. You specify which type of chart you want to display using the component’schartType
property. This component can be used to easily switch between chart types or to show a series of charts that are all different types. - ChartWidget - A universal
<Chart />
wrapped in a widget container. You can use the widget wrapping to add a title, widget styling, and more.
Although there are some differences between the different chart types, their basic usage is mostly similar. Each chart has the same base properties for working with a chart’s data, chart options, and callbacks. In addition to these base properties, some charts will have additional properties specific to their chart types.
The examples in this guide will use the generic <Chart />
component, but you can apply the code found in the examples to other chart types as well. The examples will also mostly use data from a Sisense instance, but the code in the examples can be adapted to work with data from other sources as well.
# Data Properties
Charts contain the following data properties for working with the data the chart displays:
dataSet
- Data or reference to the data the chart displaysfilters
- Filters to apply to the chart datahighlights
- Highlights that highlight data that pass certain criteria
# dataSet
The dataSet
property defines a chart’s data. The data you use for your chart can either be data queried from a data source in a Sisense instance or any explicit data.
If no data is specified, the chart uses data from the defaultDataSource
(specified in the <SisenseContextProvider />
for React projects and in the SisenseContextConfig
object for Angular projects).
The way the data is applied to a chart is defined by the chart’s dataOptions
as explained below.
# Sisense data
When using data from a Sisense instance, set the dataSet
property’s value to the name of the Sisense data source. Typically, you retrieve the data source name from a data model you create using the get-data-model
command of the Compose SDK CLI.
Under the hood, a chart executes a query to connect to the data source and load the data as specified in the dataOptions
, filters
, and highlights
as described below. You can also perform the query explicitly (using the <ExecuteQuery />
component or the useExecuteQuery()
hook in React or the QueryService
in Angular) and use the returned data as a chart’s dataSet
value. Running a query explicitly allows you to use the query results for a number of purposes, to populate multiple charts for example, instead of tying the query to a single chart.
For example, the following code snippets set a chart’s dataset using data from the Sample ECommerce data model:
# React
# Angular
// Component behavior in .component.ts
import { measureFactory } from '@sisense/sdk-data';
import * as DM from '../../sample-ecommerce';
//...
chart = {
chartType: 'column' as const,
dataSet: DM.DataSource,
dataOptions: {
category: [DM.Commerce.AgeRange],
value: [measureFactory.sum(DM.Commerce.Revenue)],
},
},
<!--Component HTML template in .component.html-->
<csdk-chart [chartType]="chart.chartType" [dataSet]="chart.dataSet" [dataOptions]="chart.dataOptions" />
# Explicit data
In addition to data from Sisense, you can use any other data with Compose SDK charts. This can be static data that you provide or data from a 3rd party.
The Compose SDK charts expect data in a specific tabular format. The data must be an object containing an array of Column
objects and a two-dimensional array of row data. The Column
objects have name
and type
properties. The row data can be made up of strings and numbers for raw data or Cell
objects for data that includes some formatting information in addition to the raw data.
Once you have your data formatted properly, you can use that data by setting the data object as the value of the dataSet
property.
For example, the following code snippets set a chart’s dataset using static data:
# Sample data
const sampleData = {
columns: [
{ name: 'Years', type: 'date' },
{ name: 'Quantity', type: 'number' },
{ name: 'Units', type: 'number' },
],
rows: [
['2019', 5500, 1500],
['2020', 4471, 7000],
['2021', 1812, 5000],
['2022', 5001, 6000],
['2023', 2045, 4000],
],
};
# React
# Angular
// Component behavior in .component.ts
chart = {
chartType: 'column' as const,
dataSet: sampleData,
dataOptions: {
category: [{ name: 'Years', type: 'date' }],
value: [{ name: 'Quantity', type: 'number' }],
},
},
<!--Component HTML template in .component.html-->
<csdk-chart [chartType]="chart.chartType" [dataSet]="chart.dataSet" [dataOptions]="chart.dataOptions" />
# filters
The filters
property defines filters to apply to a chart’s data. You can create filters using filtering functions or connect your filtering to filter UI components.
You can use filters on a single chart or use the same filter to filter multiple charts at once.
# Filter functions
The sdk-data
module contains factory functions to create text, number, and date filters on specified attributes.
Call one or more of these functions to create filters that you then use to set the value of a chart's filter
property.
Use this filtering option when you know what you want to filter on when writing your code or you want to create a dynamic filter without using Compose SDK filtering UI components.
For example, the following code snippets filter a chart’s dataset to only include data where the cost is greater than 1000.
# React
# Angular
// Component behavior in .component.ts
import { filterFactory, measureFactory } from '@sisense/sdk-data';
import * as DM from '../../sample-ecommerce';
//...
chart = {
chartType: 'column' as const,
dataSet: DM.DataSource,
dataOptions: {
category: [DM.Commerce.AgeRange],
value: [measureFactory.sum(DM.Commerce.Revenue)],
},
filters: [filterFactory.lessThan(DM.Commerce.Cost, 1000)],
};
<!--Component HTML template in .component.html-->
<csdk-chart
[chartType]="chart.chartType"
[dataSet]="chart.dataSet"
[dataOptions]="chart.dataOptions"
[filters]="chart.filters"
/>
# Filter components
The sdk-ui
modules contain UI components for creating user-defined filters. You can use the filters created by these components to filter one of more charts.
Add one or more of these components to create filters that you then use to set the value of a chart's filter
property.
Use this filtering option when you want to use pre-built components to allow your users to set filters.
For example, the following code snippets filter a chart’s dataset based on the condition dimension.
# React
# Angular
// Component behavior in .component.ts
import { Filter, filterFactory, measureFactory } from '@sisense/sdk-data';
import * as DM from '../../sample-ecommerce';
//...
DM = DM;
conditionFilter = filterFactory.members(DM.Commerce.Condition, []);
onMembersFilterChange({ filter }: { filter: Filter | null }) {
if (!filter) return void console.log(filter);
this.conditionFilter = filter;
}
chart = {
chartType: 'column' as const,
dataSet: DM.DataSource,
dataOptions: {
category: [DM.Commerce.AgeRange],
value: [measureFactory.sum(DM.Commerce.Revenue)],
},
filters: [this.conditionFilter],
};
<!--Component HTML template in .component.html-->
<csdk-chart
[chartType]="chart.chartType"
[dataSet]="chart.dataSet"
[dataOptions]="chart.dataOptions"
[filters]="[conditionFilter]"
/>
<csdk-member-filter-tile
title="Condition"
[dataSource]="DM.DataSource"
[attribute]="DM.Commerce.Condition"
[filter]="conditionFilter"
(filterChange)="onMembersFilterChange($event)"
/>
# highlights
Highlights work in a similar fashion to filters. But, whereas filters filter the data to only show the subset of the data that matches the filter, highlights show all the data, but call attention to the data that matches the filter. Not all filters will work as highlights though. The filter dimension must match those defined in the dataOptions
of the chart (see the Chart Properties section below).
Just like filters, you can create highlights using filtering functions or connect your filtering to filter components.
You can also use filters and highlights together to first filter the data that is displayed in a chart and then highlight some of that data.
# Filter functions for highlighting
See above to learn about filtering functions. Use the filters returned by those functions to set a chart’s highlights
property.
For example, the following code snippets highlight certain age ranges in a chart.
# React
# Angular
// Component behavior in .component.ts
import { filterFactory, measureFactory } from '@sisense/sdk-data';
import * as DM from '../../sample-ecommerce';
//...
chart = {
chartType: 'column' as const,
dataSet: DM.DataSource,
dataOptions: {
category: [DM.Commerce.AgeRange],
value: [measureFactory.sum(DM.Commerce.Revenue)],
},
highlights: [
filterFactory.members(DM.Commerce.AgeRange, ['25-34', '35-44', '45-54']),
],
},
<!--Component HTML template in .component.html-->
<csdk-chart
[chartType]="chart.chartType"
[dataSet]="chart.dataSet"
[dataOptions]="chart.dataOptions"
[highlights]="chart.highlights"
/>
# Filter components for highlighting
See above to learn about filter components. Use the filters created by those components to set a chart’s highlights
property.
For example, the following code snippets highlight a chart’s data based on age range, with some default highlighting already set when the chart is loaded.
# React
# Angular
// Component behavior in .component.ts
import { Filter, filterFactory, measureFactory } from '@sisense/sdk-data';
import * as DM from '../../sample-ecommerce';
//...
DM = DM;
ageRangeFilter = filterFactory.members(DM.Commerce.AgeRange, []);
onMembersFilterChange({ filter }: { filter: Filter | null }) {
if (!filter) return void;
this.ageRangeFilter = filter;
}
chart = {
chartType: 'column' as const,
dataSet: DM.DataSource,
dataOptions: {
category: [DM.Commerce.AgeRange],
value: [measureFactory.sum(DM.Commerce.Revenue)],
},
highlights: [this.ageRangeFilter],
};
<!--Component HTML template in .component.html-->
<csdk-chart
[chartType]="chart.chartType"
[dataSet]="chart.dataSet"
[dataOptions]="chart.dataOptions"
[highlights]="[ageRangeFilter]"
/>
<csdk-member-filter-tile
title="Age Range"
[dataSource]="DM.DataSource"
[attribute]="DM.Commerce.AgeRange"
[filter]="ageRangeFilter"
(filterChange)="onMembersFilterChange($event)"
/>
# Chart Properties
Charts contain the following chart properties for working with the data and style options:
dataOptions
- Configuration for querying aggregate data and assigning data to a chartstyleOptions
- Configuration options that define the style of chart elements.
# dataOptions
A chart’s data options configure how the data in a chart is aggregated and how the data is applied to a chart.
There are different configurations for different types of charts. Some types of configurations are:
- Cartesian
- Categorical
- Scatter
- Indicator
Let’s take a look at the data options for Cartesian charts. After understanding how those work, you should have no problem using the other types of data options as well.
Cartesian charts can include multiple values on both the X and Y axes, as well as a break-down by categories. The cartesian data options contain the following properties:
category
value
breakBy
seriesToColorMap
In the examples below, we’ll show the data options that replace the placeholder in the following chart code.
# React
import { Chart } from '@sisense/sdk-ui';
import * as DM from '../sample-ecommerce';
import { measureFactory } from '@sisense/sdk-data';
//...
<Chart
chartType={'bar'}
dataSet={DM.DataSource}
dataOptions={{
/* data options go here */
}}
/>;
# Angular
// Component behavior in .component.ts
import { measureFactory } from '@sisense/sdk-data';
import * as DM from '../../sample-ecommerce';
chart = {
chartType: 'column' as const,
dataSet: DM.DataSource,
dataOptions: {
/* data options go here */
},
};
<!--Component HTML template in .component.html-->
<csdk-chart [chartType]="chart.chartType" [dataSet]="chart.dataSet" [dataOptions]="chart.dataOptions" />
# category and value
The category
and value
properties determine how the axes of a chart are set up.
Typically, a category
is a dimension in your data model. These are entities such as dates, people, or location. This information doesn’t change that often.
Typically, a value
is a fact in your data model. These contain quantitative and numerical data such as transactions, inventory, or performance data. This information changes often and is generally the data you want to analyze using a chart. Often, you will run some sort of aggregation or other measure function to aggregate, summarize, and accumulate values.
Let’s take a look at some examples of charts using the category
and value
properties.
This is the simplest example where we have a single category
and a single value
. This chart shows the sum of revenue for a number of age ranges.
# React
# Angular
dataOptions: {
category: [DM.Commerce.AgeRange],
value: [measureFactory.sum(DM.Commerce.Revenue, 'Sum of Revenue')],
},
This example adds an additional value
to the chart . This chart shows the sum of cost alongside the sum of revenue for a number of age ranges.
# React
# Angular
dataOptions: {
category: [DM.Commerce.AgeRange],
value: [
measureFactory.sum(DM.Commerce.Revenue, 'Sum of Revenue'),
measureFactory.sum(DM.Commerce.Cost, 'Sum of Cost'),
],
},
This example is similar to the one above in that it uses two value
measures, but it changes the type of chart used in the second value
and adds a right-side axis. This chart shows the sum of revenue and quantity for a number of age ranges.
# React
# Angular
dataOptions: {
category: [DM.Commerce.AgeRange],
value: [
measureFactory.sum(DM.Commerce.Revenue, 'Sum of Revenue'),
{
column: measureFactory.sum(DM.Commerce.Quantity, 'Sum of Quantity'),
chartType: 'line',
showOnRightAxis: true,
},
],
},
This example adds an additional category
to a chart instead of an additional value
. Notice how there are now labels across both the bottom and top of the Y-axis. This chart shows the sum of revenue for a number of condition types and age ranges. In this case it is probably preferable to use a breakBy
instead of adding a second category, as explained below.
# React
# Angular
dataOptions: {
category: [DM.Commerce.AgeRange, DM.Commerce.Condition],
value: [measureFactory.sum(DM.Commerce.Revenue, 'Sum of Revenue')],
},
This example has two category
attributes and two value
measures. This chart shows the sum of revenue alongside the sum of cost for a number of condition types and age ranges.
# React
# Angular
dataOptions: {
category: [DM.Commerce.AgeRange, DM.Commerce.Condition],
value: [
measureFactory.sum(DM.Commerce.Revenue, 'Sum of Revenue'),
measureFactory.sum(DM.Commerce.Cost, 'Sum of Cost'),
],
},
# breakBy and seriesToColorMap
The breakBy
property, optionally determines how categories are broken down into subcategories. You can also use the seriesToColorMap
property to customize the color of the broken down subcategories.
Let’s take a look at some examples of charts using the breakBy
and seriesToColorMap
properties.
This example has a single category
and a single value
, but the categories are broken down by an additional attribute. This chart shows the sum of revenue for a number of condition types and age ranges.
# React
# Angular
dataOptions: {
category: [DM.Commerce.AgeRange],
value: [measureFactory.sum(DM.Commerce.Revenue, 'Sum of Revenue')],
breakBy: [DM.Commerce.Condition],
},
This example shows the same data as the previous example, but the subcategories are colored using the colors defined in the series color map.
# React
# Angular
dataOptions: {
category: [DM.Commerce.AgeRange],
value: [measureFactory.sum(DM.Commerce.Revenue, 'Sum of Revenue')],
breakBy: [DM.Commerce.Condition],
seriesToColorMap: {
New: '#7CB518',
Refurbished: '#F3DE2C',
Used: '#FB6107',
Unspecified: '#FBB02D',
},
},
# styleOptions
A chart’s style options configure the styling of the chart’s elements.
There are many different types of style configurations. The type of configuration you use for a specific chart depends on the chart type. Each of the configuration types has a different set of properties that are tailored to the types of charts they apply to.
Note that you can achieve additional styling of your charts using the <ThemeProvider />
.
For example, the following code snippets limit the number of slices in the pie chart and remove some of the labeling using style options.
# React
# Angular
// Component behavior in .component.ts
import { filterFactory, measureFactory } from '@sisense/sdk-data';
import * as DM from '../../sample-ecommerce';
//...
chart = {
chartType: 'pie' as const,
dataSet: DM.DataSource,
dataOptions: {
category: [DM.Commerce.AgeRange],
value: [measureFactory.sum(DM.Commerce.Revenue)],
},
styleOptions: {
convolution: {
enabled: true,
independentSlicesCount: 4,
selectedConvolutionType: 'bySlicesCount',
},
labels: {
categories: false,
},
width: 550,
height: 400,
},
};
<!--Component HTML template in .component.html-->
<csdk-chart
[chartType]="chart.chartType"
[dataSet]="chart.dataSet"
[dataOptions]="chart.dataOptions"
[styleOptions]="chart.styleOptions"
/>
# Callbacks
Charts contain callback properties for defining functions that are called when certain events occur. Most charts have the following callback properties:
onBeforeRender
onDataPointClick
onDataPointContextMenu
onDataPointsSelected
These callbacks allow you to perform actions to change a chart’s behavior or to react in some way to events that happen on a chart.
The onBeforeRender
callback allows you to customize the underlying chart element before it is rendered to your users. The callback receives an object representing the Highcharts options of the underlying chart element. Use the options object to change options values and then return the modified options object. The returned options are then used when rendering your chart.
The onData*
callbacks allow you to react to user interactions with your chart. The callbacks receive information about the data point the user is interacting with as well as an event object for the native event that occurred. You can use that information to respond to the event in any way you want.
For example, the following code snippets remove the tooltip that shows by default when you hover over data points in the chart and replace it with an element that shows the data point information when the data point is clicked.
# React
# Angular
// Component behavior in .component.ts
import { Component } from '@angular/core';
import { measureFactory } from '@sisense/sdk-data';
import { DataPoint, HighchartsOptions } from '@sisense/sdk-ui';
import * as DM from '../../sample-ecommerce';
type PointInfo = { range: string; value: string } | null;
//...
pointInfo: PointInfo;
chart = {
chartType: 'column' as const,
dataSet: DM.DataSource,
dataOptions: {
category: [DM.Commerce.AgeRange],
value: [measureFactory.sum(DM.Commerce.Revenue)],
},
};
onBeforeRender(options: HighchartsOptions) {
if (options.tooltip) options.tooltip.enabled = false;
return options;
}
onDataPointClick(...args: any[]) {
const clickedPoint: DataPoint = args[0].point;
this.pointInfo = {
range: clickedPoint.categoryDisplayValue!,
value: this.formatNumber(clickedPoint.value),
};
}
<!--Component HTML template in .component.html-->
<div class="pointInfo" *ngIf="pointInfo">Range: {{ pointInfo.range }} | Value {{ pointInfo.value }}</div>
<csdk-chart
[chartType]="chart.chartType"
[dataSet]="chart.dataSet"
[dataOptions]="chart.dataOptions"
[beforeRender]="onBeforeRender"
(dataPointClick)="onDataPointClick($event)"
/>