This topic explains how to develop a custom widget for a rounded corner ring chart using ECharts in Quick BI.
Example chart
For the detailed code, see the complete code example.
Step 1: Create a project
Create a custom widget project and install dependencies to initialize it.
See Getting Started.
npm init qbi-app myEcharts cd myEcharts yarn
Register the widget in the or Quick BI international console as shown in the figure below.
NoteSelect Professional mode for the development mode.
For online editing tutorials, see Tutorials: Quickly Insert ECharts Code in Online Edit Mode.
Install ECharts.
Run the following command to install ECharts type definitions.
yarn add -D @types/echarts
Choose one of the following methods to install ECharts:
Third-party CDN introduction: This method can enhance loading performance.
To include third-party library dependencies for the custom widget, enter the
echarts
CDN address in the specified field. For more information, see the referenced document.Configure
webpack.config.js
in the project's root directory and add anexternals
configuration.// webpack.config.js externals: { lodash: '_', react: 'React', 'react-dom': 'ReactDOM', moment: 'moment', echarts: 'echarts', // Add a new item },
npm installation: Install using
npm
oryarn
.yarn add echarts
In the widget management list, locate the target widget and click the Debug icon.
The system will automatically redirect you to the corresponding dashboard for debugging. See Debug Widget.
Step 2: Configure meta
Meta configuration includes settings for the data and style panels.
Configure the Data Panel
Customize dataSchema
in meta.ts
to define how the chart retrieves data. You can often modify the meta provided in the template-based project. Common modifications include the following:
areaName: The display name of the field
required: Whether the field is mandatory
maxColumn: The maximum number of fields that can be included
To display 1 dimension and 3 measures, simply adjust the corresponding maxColumn
. Here's an example:
// meta.ts
const componentMeta: Interfaces.ComponentMeta = {
propsSchema: {
dataSchema: {
areas: [
{
id: "drill",
name: "Drill/Dimension",
queryAxis: "drill",
rule: {
fieldTypes: ["dimension"],
required: false, // Whether it is a required field for updating the chart
/** Limit the number */
maxColNum: 3,
},
},
{
id: "area_row",
name: "Dimension",
queryAxis: "row",
rule: {
fieldTypes: ["dimension"],
maxColNum: 1, // Maximum number of allowed fields
required: true, // Whether it is a required field for updating the icon
},
},
{
id: "area_column",
name: "Measure",
queryAxis: "column",
rule: {
fieldTypes: ["dimension", "measure"],
maxColNum: 3, // Maximum number of allowed fields
required: true, // Whether it is a required field for updating the icon
},
},
{
id: "filters",
name: "Filter", // Name
queryAxis: "filters",
rule: {
fieldTypes: ["dimension", "measure"],
required: false,
},
},
],
resultDisplay: {
/** Limit the number of rows */
upLimit: 1000,
},
},
},
};
You can create a data panel as illustrated below. Refer to the
dataSchema
for detailed configuration instructions. For more information, see the referenced document.
Configuring the Style Panel
The styleSchema
defines the configuration for the style panel, which you can customize to suit your specific scenario. The requirements for the style panel in this example include the following:
You can choose to display or hide the legend.
You can specify the starting angle as a number.
Upon analyzing the requirements, it is clear that a checkbox
and a number
editor must be defined. Consequently, within styleSchema
, set type: 'switch'
and type: 'number'
. (For a list of currently supported editors, see schema.type.)
const componentMeta: Interfaces.ComponentMeta = {
propsSchema: {
styleSchema: {
schema: {
type: 'object',
className: 'tabs-uischema-container',
props: { mode: 'collapse' },
properties: {
// Fill in the custom properties you need here
display: {
type: 'object',
title: 'Display settings',
properties: {
showLegend: {
type: 'switch',
id: 'showLegend',
defaultValue: true,
props: {
mode: 'checkbox',
label: 'Display legend',
},
},
startAngle: {
title: 'Starting angle',
id: 'startAngle',
type: 'number',
defaultValue: 0,
props: {
placeholder: 'Please enter the starting angle',
maxLength: 140,
},
},
},
},
},
},
},
},
};
At this stage, the style panel will automatically generate these two editors. You can retrieve the values entered in the editors from the customProps.viewConfig
within the custom widget.
Step 3: Develop the echarts chart
To develop the chart, you need to invoke the setOption(option)
method. The following provides guidance on transforming properties from Quick BI into parameters that echarts can accept.
Initialize an ECharts instance.
In the
mount
method, you can create anecharts
instance.// src/component.ts mount(props: Interfaces.LifecycleProps<Interfaces.ComponentProps>) { // ... this.chart = echarts.init(props.container as HTMLDivElement); this.setOption(props); }
Transform the data.
Encapsulate the
setOption
method to facilitate its invocation during the mounting and updating phases.customProps.data
is a two-dimensional array.customProps.data[i]
represents a row of data in the database table, and each row includes the values corresponding to the configured dimension and measure fields.customProps.data[i][j]
represents the value of a cell in the database table. For the data structure, see Custom widget API, where fieldId is the field ID of the dimension and measure.Establish a map of fieldId to array index to easily retrieve values through fieldId.
// src/component.ts setOption(props: Interfaces.LifecycleProps<Interfaces.ComponentProps>) { // Chart data const data = props.customProps.data; // Data panel format settings const fieldSettingMap = props.customProps.viewConfig.fieldSettingMap; // First row of data const [firstRow] = data; // The position of each row of data is fixed. By establishing a mapping relationship between array index and fieldId, it is convenient to obtain values through fieldId const fieldColumnIndexMap: { [key: string]: number; } = firstRow.reduce( (prev, curr, i: number) => ({ ...prev, [curr.fieldId]: i, }), {}, ); }
Configure the series.
You can retrieve series settings using
customProps.dataConfig
for the dimension and measure fields set up in the data panel.// src/component.ts setOption(props: Interfaces.LifecycleProps<Interfaces.ComponentProps>) { // ... data // Filter out all measures const columnsFields = props.customProps.dataConfig.find(each => each.areaType === 'column')?.fields ?? []; // Data panel data format settings const fieldSettingMap = props.customProps.viewConfig.fieldSettingMap; // Convert format const series = columnsFields.map((each, i) => { const filedSetting = fieldSettingMap[each.fieldId]; return { id: each.fieldId, type: 'bar', // According to the mapping of fieldId and array index, the data value of each row data: data.map(row => row[fieldColumnIndexMap[each.fieldId]]?.value), coordinateSystem: 'polar', // Set alias name: filedSetting?.aliasName ?? each.showName, }; }); // ... this.chart.setOption({ series, // ... }); }
Set the category by taking the first dimension, as the rounded corner ring chart accepts only one.
Specify the category. Because the rounded corner ring chart accepts only one dimension, select the first one.
// src/component.ts setOption(props: Interfaces.LifecycleProps<Interfaces.ComponentProps>) { // Filter out all measures const rowFields = props.customProps.dataConfig.find(each => each.areaType === 'row')?.fields ?? []; // Meta limits only one dimension const [onlyRow] = rowFields; const category = data.map(row => row[fieldColumnIndexMap[onlyRow?.fieldId]]?.value); // ... this.chart.setOption({ radiusAxis: { type: 'category', data: category, z: 10, }, // ... }); }
Review the style panel settings.
You can retrieve the values of forms configured in the style panel using
customProps.viewConfig
. For instance, the form name for the checkbox editor is showLegend, while for the number input box, it is startAngle. Since both are located under the display category, you can access them viacustomProps.viewConfig.display?.showLegend
.// src/component.ts setOption(props: Interfaces.LifecycleProps<Interfaces.ComponentProps>) { const showLegend = props.customProps.viewConfig.display?.showLegend; const startAngle = props.customProps.viewConfig.display?.startAngle; // Set echarts this.chart.setOption({ angleAxis: { startAngle, }, legend: { show: viewConfig.display?.showLegend, data: legend, top: 10, padding: 0, }, // ... }); }
Create effects such as drill down, filter interaction, and jumping.
Quick BI offers the
customProps.dispatch
method, which allows you to perform actions such as drilling down, filter interaction, and jumping. The dataIndex refers to the array index of the dimension to be displayed withincustomProps.data
.// component.ts const dispatch = props.customProps.dispatch; if (typeof dispatch === 'function') { // Drill down/Filter interaction/Jump event echarts.on('click', (serie: any) => { dispatch({ type: 'select', payload: { dataIndex: serie.dataIndex, // dataIndex is the array index of the clicked row in data }, }); }); // Click blank event, used to adapt to mobile drill down echarts.getZr().on('click', function (e) { if (!e.target) { dispatch({ type: 'cancelSelect', }); } }); }
After completing these steps, the chart will be displayed. Modify the style and adjust the data format as needed. For details, see the comments in the complete code example.
Step 4: Packaging
Package the custom widget after development is complete.
npm run pack
The output is located in the build
folder. You can upload this through the custom widget platform to publish your widget.
For details on packaging and publishing, see Packaging and Publishing a Widget in Quick BI.