Building an Apache ECharts Dashboard with Vue 3 and Cube
Adnan Rahić
Posted on February 10, 2022
This guest post was written by Ashutosh Singh.
Ashutosh is a writer, learner, and JavaScript developer who enjoys writing articles that help people.
You can get in touch with him through his website or on Twitter!
Apache ECharts is a powerful charting and visualization library. When paired with an analytics API like Cube, you can build some incredibly compelling dashboards.
In this tutorial, you’ll learn how to create a data visualization dashboard using Vue.js and Cube, a Headless BI and analytics APIs for building data applications. You’ll also learn how you can use Apache ECharts, an open source JavaScript visualization library, to create charts and visual designs. When you’re finished, you’ll have created an application like the one below.
If you want to jump right into the code, you can check out the GitHub repo and follow along. You also have access to the deployed version.
What Is Cube?
Cube is an open source analytics framework used for building high-performance data applications. With Cube, you can connect your data warehouses like MongoDB, PostgreSQL, and Snowflake to your frontend application like Vue.js to build data applications like real-time dashboards faster and more flexibly than other charting and visualization libraries.
What Is Apache ECharts?
Apache Echarts is a powerful, interactive charting and data visualization library that can be used with most browsers to create stunning charts, visual designs, graphs, and more.
Apache Echarts is often used with data and monitoring tools to create custom charts that can provide professional data analysis in an elegant design. When compared to its alternatives like D3.js, ECharts is more powerful, easy to adapt, and has better performance.
Here are just a few reasons why you should use Apache ECharts:
- It supports tons of charts like line series, bar series, scatter series, pie charts, candlestick series, boxplot series for statistics, treemap series, sunburst series, parallel series for multidimensional data, funnel series, and gauge series. It’s also incredibly easy to combine and create new charts.
- You can toggle between canvas and SVG rendering without any hassle.
- It supports multidimensional analyses of data sets with data transformations like filtering, clustering, and regression.
- It helps you create stunning, responsive, and highly customisable designs.
- With over 50,000 stars on GitHub, ECharts has one of the most active open source communities, ensuring the healthy development of the project and tons of resources to take inspiration from.
- ECharts is optimized for mobile interaction.
The Museum of Modern Art Data Set
The Museum of Modern Art (MoMA) collection data is a public data set available in JSON and CSV formats. It’s published and maintained by MoMA and contains around 140,000 records. You can use this data set for your side projects and demo applications since it’s available with a CC0 License.
In this tutorial, you’ll use this data set to create a dashboard with charts and tables using Cube, Apache ECharts, and Vue.js.
How to Set Up Cube
Before you begin, you’ll need the following:
- Knowledge of HTML, CSS, and JavaScript.
- Basic knowledge of Vue.js.
- Node and npm installed on your local dev machine.
- Any code editor of your choice like Visual Studio Code.
In this section, you’ll learn how to set up Cube on your local machine and how to scaffold a new Cube project using the Cube CLI tool.
The Cube command-line interface (CLI) can be used to quickly create a new Cube service and generate schemas based on your database tables.
Run the following command in the terminal to install the Cube CLI on your machine:
npm install -g cubejs-cli
Next, you need to create a new Cube service. To do that, run the following command in the terminal of your project’s root:
npx cubejs-cli create vue-echarts -d postgres
In this tutorial, you’ll be using a Postgres instance of the MoMA data set, but you can use any other database like MySQL or Oracle. You can find more about all the available databases on Cube’s website.
The last command above creates a new project named vue-echarts
with the following folder structure:
├── cube.js
├── docker-compose.yml
├── package-lock.json
├── package.json
└── schema
└── Orders.js
Orders.js
is a sample schema created by the Cube CLI tool with sample data.
cube(`Orders`, {
sql: `
select 1 as id, 100 as amount, 'new' status
UNION ALL
select 2 as id, 200 as amount, 'new' status
UNION ALL
select 3 as id, 300 as amount, 'processed' status
UNION ALL
select 4 as id, 500 as amount, 'processed' status
UNION ALL
select 5 as id, 600 as amount, 'shipped' status
`,
preAggregations: {
// Pre-Aggregations definitions go here
// Learn more here: https://cube.dev/docs/caching/pre-aggregations/getting-started
},
measures: {
count: {
type: `count`
},
totalAmount: {
sql: `amount`,
type: `sum`
}
},
dimensions: {
status: {
sql: `status`,
type: `string`
}
}
});
The vue-echarts
project will contain a .env
file with the Cube service credentials. The .env
file will look like this:
# Cube.js environment variables: https://cube.dev/docs/reference/environment-variables
CUBEJS_DEV_MODE=true
CUBEJS_DB_TYPE=postgres
CUBEJS_API_SECRET=1bea38a48b6e92af20a7026bdb29893ce6fadb1d76edad085121f326acb7ccf0c5077ff7242af7cf8f7afc0ba5420bcb464e384c4721aeb94d54e05ed1975f30
CUBEJS_EXTERNAL_DEFAULT=true
CUBEJS_SCHEDULED_REFRESH_DEFAULT=true
CUBEJS_WEB_SOCKETS=true
Copy the CUBEJS_API_SECRET
key; you’ll use this later to connect to the Cube cluster from the Vue.js app.
Update the .env
file to include the credential keys that connect to the Postgres instance made with the MoMA data set.
CUBEJS_DB_TYPE=postgres
CUBEJS_DB_HOST=demo-db-examples.cube.dev
CUBEJS_DB_NAME=moma
CUBEJS_DB_USER=cube
CUBEJS_DB_PASS=12345
You can also connect to a local instance of Postgres by replacing the above credentials with your local Postgres instance’s credentials.
How to Generate Schema
Next, you’ll generate schema files using Cube Developer Playground.
A Cube Data Schema models raw data into meaningful business definitions. It also pre-aggregates data for optimal results. The data schema is exposed through the querying API, allowing end users to query a wide variety of analytical queries without modifying the schema itself.
Run the following command in your terminal:
cd vue-echarts
npm run dev
You’ll see the Cube Developer Playground showing all the connected database tables.
Navigate to localhost:4000 in your browser. There, you’ll see the Cube Developer Playground showing all the connected database tables. Under Tables, select public and click on Generate Schema.
Once the schema is generated successfully, you’ll see a pop-up like this:
Next, click on Build and create your first query. Once you’ve created a query similar to the one shown below, select Run.
The above query returns all the works of art present in the MoMA data set.
You can click on the JSON Query tab to get the query you created in a JSON format, which you’ll use later in the Vue project to run queries from the Vue.js frontend.
The final JSON query will look like this:
Next, you’ll create the query to get the status of orders present in the Orders
sample schema.
Click on the + icon next to Query 1 on the Cube Developer Playground to create another query to get the status of the orders.
Like the first query, you can get the query above in JSON format by clicking on the JSON Query button.
How to Install and Set Up a Vue.js Project
In this section, you’ll learn how to set up and install Vue.js. You’ll also see how you can run the queries created in the last section from the Vue.js app.
In this tutorial, you’ll use Vue CLI to create the initial Vue.js project. To install Vue CLI, run the following command:
npm install -g @vue/cli
Next, create a Vue.js project named vue-cube-echarts
by running this command in your project’s root terminal:
vue create vue-cube-echarts
When prompted to choose the preset, choose Default (Vue 3) ([Vue 3] babel, eslint)
.
Vue CLI v4.5.15
? Please pick a preset:
Default ([Vue 2] babel, eslint)
> Default (Vue 3) ([Vue 3] babel, eslint)
Manually select features
After the project has been created, you need to start the development server with the following command:
cd vue-cube-echarts
npm run serve
Navigate to http://localhost:8080/ in your browser. Now your app should look like this:
The next step is to install the Cube Vue client. Run the following command in the terminal to install @cubejs-client/core
and @cubejs-client/vue3
:
npm install @cubejs-client/core @cubejs-client/vue3
Update the App.vue
file:
<template>
<h1>Vue Cube.js ECharts</h1>
<div class="dashboard">
<div class="cards-container">
<query-builder :cubejs-api="cubejsApi" :query="totalPaintingsQuery">
<template v-slot="{ loading, resultSet }">
<div v-if="loading" class="loading">Loading...</div>
<div v-if="!loading && resultSet !== undefined">
<Card :resultSet="resultSet" title="Total Paintings" />
</div>
</template>
</query-builder>
<query-builder :cubejs-api="cubejsApi" :query="orderStatusQuery">
<template v-slot="{ loading, resultSet }">
<div v-if="loading" class="loading">Loading...</div>
<div v-if="!loading && resultSet !== undefined">
<OrderCard :resultSet="resultSet" title="Order Status" />
</div>
</template>
</query-builder>
</div>
</div>
</template>
<script>
import cubejs from "@cubejs-client/core";
import { QueryBuilder } from "@cubejs-client/vue3";
import Card from "./components/Card";
import OrderCard from "./components/OrderCard";
const cubejsApi = cubejs(
"1bea38a48b6e92af20a7026bdb29893ce6fadb1d76edad085121f326acb7ccf0c5077ff7242af7cf8f7afc0ba5420bcb464e384c4721aeb94d54e05ed1975f30",
{
apiUrl: "http://localhost:4000/cubejs-api/v1",
}
);
export default {
name: "App",
components: {
QueryBuilder,
Card,
OrderCard,
},
data() {
return {
cubejsApi,
totalPaintingsQuery: {
measures: ["Artworks.count"],
},
orderStatusQuery: {
measures: ["Orders.count"],
timeDimensions: [],
order: {
"Orders.count": "desc",
},
filters: [],
dimensions: ["Orders.status"],
},
};
},
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
padding: 0 3rem;
margin-top: 30px;
}
.dashboard {
display: flex;
justify-content: space-evenly;
gap: 1rem;
flex-wrap: wrap;
align-items: center;
}
.cards-container {
display: flex;
flex-direction: column;
justify-content: space-evenly;
gap: 1rem;
flex-wrap: wrap;
align-items: center;
}
.card-wrapper {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: fit-content;
min-width: 250px;
min-height: 100px;
padding: 2rem;
border-radius: 5px;
background-color: #fafafa;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
}
.card-title {
font-size: 1.2rem;
font-weight: bold;
margin: 0;
}
.card-content {
font-size: 2.5rem;
font-weight: bold;
color: #42b983;
padding-top: 6px;
}
</style>
In the code above, you import cubejs
from @cubejs-client/core
and QueryBuilder
from @cubejs-client/vue3
, respectively. Then you initialize a new instance of Cube by pasting the CUBEJS_API_SECRET
copied in the last section.
const cubejsApi = cubejs(
"1bea38a48b6e92af20a7026bdb29893ce6fadb1d76edad085121f326acb7ccf0c5077ff7242af7cf8f7afc0ba5420bcb464e384c4721aeb94d54e05ed1975f30",
{
apiUrl: "http://localhost:4000/cubejs-api/v1",
}
);
In the code above, you pass the QueryBuilder
as a component in the components
section used in the template
syntax.
Below, you’ll paste the queries for getting all the artwork and orders status created in the last section and copied from the JSON Query tab.
data() {
return {
cubejsApi,
totalPaintingsQuery: {
measures: ["Artworks.count"],
},
orderStatusQuery: {
measures: ["Orders.count"],
timeDimensions: [],
order: {
"Orders.count": "desc",
},
filters: [],
dimensions: ["Orders.status"],
},
};
}
In the query-builder
component, you pass the cubejs
instance and the query to be executed. The result of the executed query is passed to the child components as a resultSet object.
<query-builder :cubejs-api="cubejsApi" :query="totalPaintingsQuery">
<template v-slot="{ loading, resultSet }">
<div v-if="loading" class="loading">Loading...</div>
<div v-if="!loading && resultSet !== undefined">
<Card :resultSet="resultSet" title="Total Paintings" />
</div>
</template>
</query-builder>
The next step is to create the components that take this resultSet
object and show the corresponding result in the app.
Under src/components
, run the following command to create two new files named Card.vue
and OrderCard.vue
in the Vue project terminal:
touch src/components/Card.vue
touch src/components/OrderCard.vue
Add the following code to the Card.vue
file:
<template>
<div class="card-wrapper">
<h2 class="card-title">
{{ title }}
</h2>
<span class="card-content">
{{ count }}
</span>
</div>
</template>
<script>
export default {
name: "Card",
props: {
title: String,
resultSet: Object,
},
data() {
return {
count: this.resultSet
.rawData()
.map((item) => Object.values(item).map((value) => value))
.join(" "),
};
},
};
</script>
In the code above, you pass the resultSet
as a prop to the Card
component and parse it to display just the number of artwork available in the data set using the rawData()
method on the resultSet
object. The rawData
returns the data in its raw form. More information on the rawData()
method can be found in Cube’s docs.
Above, you also parse the array to extract the value of the Artworks.count
property using the map
and Object.values()
methods.
Add the following code to OrderCard.vue
:
<template>
<div class="card-wrapper">
<h2 class="card-title">
{{ title }}
</h2>
<div class="card-content-wrapper">
<div v-for="(item, index) in items" :key="index" class="card-content">
<span class="status">
{{ item[0].toUpperCase() }}
</span>
<span class="count">
{{ item[1] }}
</span>
</div>
</div>
</div>
</template>
<script>
export default {
name: "OrderCard",
props: {
title: String,
resultSet: Object,
},
data() {
return {
items: this.resultSet
.rawData()
.map((item) => Object.values(item).map((element) => element)),
};
},
};
</script>
<style scoped>
.card-content-wrapper {
display: flex;
justify-content: space-between;
gap: 1rem;
}
.card-content {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.status {
font-weight: bold;
font-size: 1rem;
color: darkseagreen;
}
</style>
Like Card.vue
, you use the rawData()
method on the resultSet
object and parse the result to show the required values.
To start your Cube dev server, run the following command in the project’s root directory:
cd vue-echarts
npm run dev
Now, run the following commands to start your Vue development server:
cd vue-cube-echarts
npm run serve
Navigate to http://localhost:8080/ in your browser, and your app should look like this:
The two components above show a particular analytics value: the total number of sales, the total number of users, orders’ status, orders processed, etc.
How to Create a Table Using Cube
In this section, you’ll create the query and the component to show a list of data in a tabular form. In a production app, you can use this component or query to display the list of active orders, vendors, a list of deliveries in a region, and more.
Head over to http://localhost:4000/ in the browser (i.e., the Cube Playground), and create a third query to get a list of artists with more than 1,000 works of art and their name doesn’t contain the word Unknown
. You’ll use the set
filter operator to check whether the value of the member is not NULL
. It’s also helpful to remove null entries from the result.
Similar to the queries above, you can click on Run to run this query and JSON Query to get the query in JSON format.
Update your App.vue
file and add the following code in the template
section right after the cards-container
div:
<div class="table-container">
<query-builder :cubejs-api="cubejsApi" :query="artistQuery">
<template v-slot="{ loading, resultSet }">
<div v-if="loading" class="loading">Loading...</div>
<div v-if="!loading && resultSet !== undefined">
<Table v-if="!loading" :resultSet="resultSet" />
</div>
</template>
</query-builder>
</div>
In the script
section, first import the Table
component which you'll be creating in a second:
import Table from "./components/Table";
Add the Table
component to the list of components:
export default {
name: "App",
components: {
QueryBuilder,
Card,
OrderCard,
Table,
},
...
}
Finally, add a new query named artistQuery
to the return value of the data()
function:
artistQuery:
{
"measures": ["Artworks.count"],
"timeDimensions": [],
"order": {
"Artworks.count": "desc"
},
"dimensions": ["Artworks.artist"],
"filters": [
{
"member": "Artworks.count",
"operator": "gte",
"values": ["1000"]
},
{
"member": "Artworks.artist",
"operator": "set"
},
{
"member": "Artworks.artist",
"operator": "notContains",
"values": ["Unknown"]
}
]
},
Create a new file named Table.vue
under the components
directory by running the following command:
touch src/components/Table.vue
Add the following Table.vue
code:
<template>
<div v-if="!loading" class="wrapper">
<div class="table-header">
<div class="col-1">Artist</div>
<div class="col-2">Number of Paintings</div>
</div>
<div class="table-body" v-for="(item, index) in items" :key="index">
<span class="col-1">
{{ item[0] }}
</span>
<span class="col-2">
{{ item[1] }}
</span>
</div>
</div>
</template>
<script>
export default {
name: "Table",
props: {
resultSet: Object,
},
computed: {
items: function () {
return this.resultSet
.rawData()
.map((item) => Object.values(item).map((value) => `${value}`));
},
},
};
</script>
<style scoped>
.table-header,
.table-body {
display: flex;
width: 800px;
}
.col-1 {
flex: 1;
}
.col-2 {
flex: 0 0 43%;
}
.table-header {
background-color: #f5f5f5;
font-size: 1.4rem;
font-weight: bold;
}
.table-body {
background-color: #fff;
font-size: 1.2rem;
padding-bottom: 5px;
border-bottom: 1px solid #ddd;
}
.table-body > .col-2 {
color: #42b983;
}
</style>
In the code above, you use the rawData()
method to get the data from the resultSet
object and parse it to render it in a tabular form.
The data returned from the rawData()
method will look like this:
[
{ "Artworks.artist": "Eugène Atget", "Artworks.count": "5050" },
{ "Artworks.artist": "Louise Bourgeois", "Artworks.count": "3335" },
{ "Artworks.artist": "Ludwig Mies van der Rohe", "Artworks.count": "2645" },
...
];
Your code will look like the following after parsing it with the map
and Object.values()
method:
[
["Eugène Atget", "5050"],
["Louise Bourgeois", "3335"],
["Ludwig Mies van der Rohe", "2645"],
...
];
Head over to http://localhost:8080/ in your browser. Your app should now look like this:
How to Add Apache ECharts to the Vue.js App
In this section, you’ll learn how to install and create different types of charts using Apache ECharts, an open source JavaScript visualization library. You’ll create a pie chart and a bar chart using the data returned from the Cube REST API.
Run the following commands in the Vue project directory to install the echarts
and vue-echarts
packages:
npm install echarts vue-echarts
The first chart you’ll create is the pie chart, which shows the different classifications of artworks. Go to http://localhost:4000/#/build?query={}, create the fourth query below, and copy its JSON format from the JSON Query tab.
Then create a new query named paintingsByClassificationQuery
in the App.vue
file using the query copied from the last step:
paintingsByClassificationQuery:
{
"measures": ["Artworks.count"],
"timeDimensions": [],
"order": {
"Artworks.count": "desc"
},
"dimensions": ["Artworks.classification"],
"filters": [
{
"member": "Artworks.count",
"operator": "gte",
"values": ["1000"]
}
]
},
Create a new file named PieChart
under the components
directory by running the following command:
touch src/components/PieChart.vue
In PieChart.vue
, start by adding the template
section which simply holds the v-chart
element:
<template>
<div class="charts-wrapper">
<v-chart class="chart" :option="option" />
</div>
</template>
In the script
section, import all the components and methods needed to create the chart from the echarts
and vue-echarts
packages.
import { use } from "echarts/core";
import { CanvasRenderer } from "echarts/renderers";
import { PieChart } from "echarts/charts";
import {
GridComponent,
TooltipComponent,
LegendComponent,
TitleComponent,
} from "echarts/components";
import VChart, { THEME_KEY } from "vue-echarts";
Now you need to use the use
method to register the components needed and imported.
use([
CanvasRenderer,
PieChart,
GridComponent,
TitleComponent,
TooltipComponent,
LegendComponent,
]);
Add the exports:
export default {
name: "PieChart",
components: {
VChart,
},
props: {
title: String,
resultSet: Object,
},
provide: {
[THEME_KEY]: "dark",
},
}
Now use the Vue.js setup
function and pass the props (i.e., the resultSet
object).
Below, you’ll parse the resultSet
object to return all the names of the classification in the headers
array. The PieCharts
expects the data to be in an object with keys name
and value
(for example: {name: Photograph, value: 31367}
). Then, you parse the resultSet
to store the data in this format in the data
array. Add this code inside the export:
setup(props) {
const headers = props.resultSet
.rawData()
.map((item) => Object.values(item)[0]);
const data = props.resultSet.rawData().map((item) => {
const currentItem = Object.values(item);
return { name: currentItem[0], value: currentItem[1] };
});
}
Now you need to create the option
, which contains the configuration of the chart, using Vue.js ref
api. Still in the setup
function, add the following after the data
declaration:
const option = ref({
title: {
text: "Paintings Classification",
left: "center",
},
tooltip: {
trigger: "item",
formatter: "{a} <br/>{b} : {c} ({d}%)",
},
legend: {
orient: "vertical",
left: "left",
data: headers,
},
series: [
{
name: "Paintings Classification",
type: "pie",
radius: "55%",
center: ["50%", "60%"],
data: data,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: "rgba(0, 0, 0, 0.5)",
},
},
},
],
});
Inside the option, you define the chart’s name, legend, and tooltip. The data
array created in the last step is passed to the data
property in the series
. Inside the series
property, you can set the type of the chart, the radius of the pie chart, the name of the chart, etc.
Finally, return the option
object:
return { option };
Here's the complete script
section for your reference:
<script>
export default {
name: "PieChart",
components: {
VChart,
},
props: {
title: String,
resultSet: Object,
},
provide: {
[THEME_KEY]: "dark",
},
setup(props) {
const headers = props.resultSet
.rawData()
.map((item) => Object.values(item)[0]);
const data = props.resultSet.rawData().map((item) => {
const currentItem = Object.values(item);
return { name: currentItem[0], value: currentItem[1] };
});
const option = ref({
title: {
text: "Paintings Classification",
left: "center",
},
tooltip: {
trigger: "item",
formatter: "{a} <br/>{b} : {c} ({d}%)",
},
legend: {
orient: "vertical",
left: "left",
data: headers,
},
series: [
{
name: "Paintings Classification",
type: "pie",
radius: "55%",
center: ["50%", "60%"],
data: data,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: "rgba(0, 0, 0, 0.5)",
},
},
},
],
});
},
};
</script>
Add some CSS for styling:
<style scoped>
.chart {
height: 400px;
}
</style>
Update the App.vue
file to import this PieChart.vue
file. Import the PieChart
component and add it to the components
declaration:
...
import PieChart from "./components/PieChart";
...
export default {
name: "App",
components: {
QueryBuilder,
Card,
OrderCard,
Table,
PieChart,
},
...
}
Add a new section under template
in the App.vue
file:
<div class="charts-section">
<query-builder
:cubejs-api="cubejsApi"
:query="paintingsByClassificationQuery"
>
<template v-slot="{ loading, resultSet }">
<div v-if="loading" class="loading">Loading...</div>
<div v-if="!loading && resultSet !== undefined">
<PieChart
v-if="!loading"
title="Classification of Paintings"
:resultSet="resultSet"
/>
</div>
</template>
</query-builder>
</div>
Then head over to http://localhost:8080/ in the browser. Your chart should now look like this:
Next, you need to create a bar chart using Apache ECharts. To do this, run the following command to create a BarChart.vue
file under the components
directory.
touch src/components/BarChart.vue
Add the following code to BarChart.vue
:
<template>
<div class="charts-wrapper">
<v-chart class="chart" :option="option" />
</div>
</template>
<script>
import { use } from "echarts/core";
import { CanvasRenderer } from "echarts/renderers";
import { BarChart } from "echarts/charts";
import {
GridComponent,
TooltipComponent,
LegendComponent,
TitleComponent,
} from "echarts/components";
import VChart, { THEME_KEY } from "vue-echarts";
import { ref } from "vue";
use([
CanvasRenderer,
BarChart,
GridComponent,
TitleComponent,
TooltipComponent,
LegendComponent,
]);
export default {
name: "PieChart",
components: {
VChart,
},
props: {
title: String,
resultSet: Object,
},
provide: {
[THEME_KEY]: "light",
},
setup(props) {
const headers = props.resultSet
.rawData()
.map((item) => Object.values(item)[0]);
const data = props.resultSet.rawData().map((item) => {
const currentItem = Object.values(item);
return currentItem[1];
});
const option = ref({
title: {
text: "Paintings by Nationality",
left: "center",
},
tooltip: {
trigger: "item",
formatter: "{a} <br/>{b} : {c} ({d}%)",
},
xAxis: {
type: "category",
data: headers,
},
yAxis: {
type: "value",
},
series: [
{
name: "Paintings by Nationality",
type: "bar",
showBackground: true,
backgroundStyle: {
color: "rgba(180, 180, 180, 0.2)",
},
data: data,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: "rgba(0, 0, 0, 0.5)",
},
},
},
],
});
return { option };
},
};
</script>
<style scoped>
.chart {
height: 400px;
}
</style>
Like PieChart
, here you import the necessary components and then parse the resultSet
object to get data in the required format. In this case, BarChart
has an array of values and passes it to the vue-chart
component via the option
prop.
Create a new query named paintingsByNationalityQuery
in your App.vue
file:
paintingsByNationalityQuery:
{
"measures": ["Artworks.count"],
"dimensions": ["Artworks.nationality"],
"timeDimensions": [],
"order": {
"Artworks.dateacquired": "asc"
},
"filters": [
{
"member": "Artworks.count",
"operator": "gte",
"values": ["1000"]
}
]
},
And then import the BarChart.vue
file in App.vue
:
<script>
...
import BarChart from "./components/BarChart";
...
export default {
name: "App",
components: {
QueryBuilder,
Card,
OrderCard,
Table,
PieChart,
BarChart
},
...
}
Add this BarChart
under the charts-section
div like this:
<query-builder :cubejs-api="cubejsApi" :query="paintingsByNationalityQuery">
<template v-slot="{ loading, resultSet }">
<div v-if="loading" class="loading">Loading...</div>
<div v-if="!loading && resultSet !== undefined">
<BarChart
v-if="!loading"
title="Paintings by Nationality"
:resultSet="resultSet"
/>
</div>
</template>
</query-builder>
After adding BarChart
, your chart will look like this:
And your final app will look like this:
Conclusion
In this tutorial, you learned how you can use Cube, an open source analytical API platform, to create components for a real-time dashboard using Vue.js. You also learned how to create charts for this dashboard using Apache ECharts.
For additional information to help get you started, take a look at the official Cube docs.
Please don't hesitate to like and bookmark this post, write a comment, and give a star to Cube on GitHub. I hope that you'll try Cube, Apache ECharts, and Vue.js in your next production gig or your next pet project.
Posted on February 10, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.