Building Reusable Components in Canvas Dashboard
With Canvas Dashboard, you can define visuals and components once and reuse them across multiple dashboards. This document goes through a simple example to demonstrate the reusability capability.
Reusable Component Example
The Setup
Let's say you have a dashboard with the following syntax:
Dashboard my_dashboard {
// metadata
title: 'My Canvas Dashboard'
description: 'My new canvas dashboard'
// collection of blocks
block t1: TextBlock {
content: @md
Hello world
;;
}
block f1: FilterBlock {
type: 'field'
label: 'User role'
source: FieldFilterSource {
dataset: 'tenant_user'
field: ref('public_users', 'role')
}
}
block v1: VizBlock {
label: 'A pie chart'
viz: PieChart {
dataset: 'tenant_user'
legend: ref('public_users', 'role')
series {
field {
ref: ref('public_users', 'id')
aggregation: 'sum'
}
}
}
}
// layout
view: CanvasLayout {
width: 1200
height: 1200
margin: 10
block f1 {
position: pos(600, 0, 300, 70)
}
block v1 {
position: pos(0, 70, 600, 600)
}
}
}
Reusing Block and Filters within another dashboard
You can refer to your existing viz and filter blocks using the syntax my_original_dashboard.block.block_name
. For example:
Dashboard another_dashboard {
// metadata
title: 'Another Canvas Dashboard'
description: 'Another canvas dashboard'
// collection of reused blocks from my_dashboard
block t1: my_dashboard.block.t1
block f1: my_dashboard.block.f1
block v1: my_dashboard.block.v1
// layout
view: CanvasLayout {
width: 1200
height: 1200
margin: 10
block f1 {
position: pos(600, 0, 300, 70)
}
block v1 {
position: pos(0, 70, 600, 600)
}
}
}
With AML Extend, you can also customize the reused block like below
Dashboard another_dashboard {
// other properties omitted
block v1: my_dashboard.block.v1.extend({
label: "A different label"
})
}
Reusing independent Block and Filters
Alternatively, you can put the viz block and filter in a separate file and reuse them with AML Constant like so:
VizBlock myviz {
label: 'A pie chart'
viz: PieChart {
dataset: 'tenant_user'
legend: ref('public_users', 'role')
series {
field {
ref: ref('public_users', 'id')
aggregation: 'sum'
}
}
}
}
FilterBlock myfilter {
type: 'field'
label: 'User role'
source: FieldFilterSource {
dataset: 'tenant_user'
field: ref('public_users', 'role')
}
}
Then you can create a new dashboard
Dashboard my_reused_dashboard {
title: 'My reused Dashboard'
block f1: myfilter
block v1: myviz
...
}
Compared to the previous method, placing the reused blocks in a separate file offers a cleaner structure. However, it can make editing those blocks more challenging as you need to put them in a concrete dashboard to edit them in the UI. Ultimately, the choice between methods depends on your preferences and specific needs.
Parameterizing components
You can also use Func to parameterize your component, like so:
Func myvizBlockWithDataset(dataset: String) {
VizBlock {
label: 'A pie chart'
viz: PieChart {
dataset: dataset
legend: ref('public_users', 'role')
series {
field {
ref: ref('public_users', 'id')
aggregation: 'sum'
}
}
}
}
}
and use it like this
Dashboard my_reused_dashboard {
...
block v1: myvizBLockWithDataset('tenant_user')
...
}
Reused blocks
A Reused Block is an Analytics Block that is explicitly and programmatically defined by users to be used in Canvas Dashboards.
Why do you need Reused Blocks?
Normally, when you use Visual Editor to develop Canvas Dashboards, Holistics takes care of code generation under the hood to ensure that the generated code correctly reflects how your dashboard works. There are multiple ways to programmatically achieve the same outcome, so we pick a particular path to generate code so that you don't have to worry about it.
But there are cases where you may want to explicitly define Analytics Blocks as code yourself:
- Build Reusable Components in Canvas Dashboard
- Build a Dashboard with Multiple Similar Charts
- Build Reusable Dashboards for Multiple Clients
What happens when you define Reused Blocks?
When you explicitly define an Analytics Block as a reusable piece of code, it becomes a Reused Block which cannot be edited using the Visual Editor. You must switch to code mode and edit the code yourself. This behavior aims to avoid accidentally replacing user-defined code with auto-generated code.