How to use D3js with WebComponents
Make powerful graphs with D3js and Stencil
D3 is a fantastic open source library for data visualization developed originally by Mike Bostock. The great variety of tools it offers allow to make rare graphs from scratch or using pre-built templates. The possibilities offered by D3 are unlimited, you only need to have a look at their gallery.
If you have already worked with D3 you will know that apart from getting astonishing graphs you also end up with a bunch of scripts for formatting data, iterating over SVG elements, services to communicate with the server, models, etc.. All of these, probably, in the very middle of a project poorly related with the graphs itself, a real mess!
Luckily, the world of Web Components it is more accessible than ever and it is the perfect tool for creating your own graphic hub well encapsulated and reusable. On Custom Elements Everywhere you may check if Web Components are compatible with your preferred development framework.
StencilJS
Stencil is a Web Components, or more specifically Custom Elements, a compiler that uses the main features of the most known web development frameworks.
This tool has been developed by the IonicFramework to make it easy to make compatible components with multiple web development frameworks, towards an agnostic framework idea.
Thus, using D3 in a project based on the Web Components (Custom Components) standards using StencilJS is an elegant and easy to accomplish solution if you want to have a single reusable graphing project.
First Step: Creating a Stencil Project
Firstly, install the latest version of StencilJS using npm
for instance and initialize the base project:
npm install @stencil/core@latest --save-exact
npm init stencil
Choose component
option with the arrow keys and set the project name. The CLI of Stencil will create a project folder where you would find src
folder which contains the first component generated by default: my-component
. The .tsx
file of the component folder is the one containing the main logic of it.
Now check that everything is working properly by typing the start
command from the root project folder on your console.
npm run start
A new browser window should open showing the HelloWorld! of Stencil, a bit dull to be honest.
Step 2: Import D3 and Create a Graph
Once you have launched the project, any update in the code will be rendered on the browser. Now, we only have to import D3 into the code of the component. First, we need to install it using npm
:
npm install d3 --save
Usually, when we work with D3 in a Javascript code we import all reference at once on a d3 alias like this: import * from ‘d3.js'
. However, since the last version and using Typescript we will have to import different modules individually. This is a bit tedious but it would help us to make the app light-weighted. In this case, we are using a pie chart so we will import the following modules:
import { select } from 'd3-selection'
import { pie, arc } from 'd3-shape';import { scaleOrdinal } from 'd3-scale';
import { quantize } from 'd3-interpolate';
import { interpolateCool } from 'd3-scale-chromatic';
select
operator allows getting reference of thehtml
elements which we want to use or modify.pie
operator is responsible for generating the data structure andarc
is the tool that allows us to generate the angles values and radio, needed to draw the chart.scaleOrdinal
,quantize
andinterpolateCool
operators help us to generate multiple colors depending on the value of each portion of the chart.
With this, we got all set and we only need to know where to place the D3 code. The basic structure of the component would be something like this:
Stencil API offers a bunch of decorators and methods that allow us to interact with the component and his lifecycle.
Prop()
This decorator allows getting inputs from the outer world of the component. In our case, those will be the graph data. These inputs are provided when using our component in html.
In fact, if we look a the project files, src/index.html
contains the components generated (only one in this case) and we may see that the instantiation of the component is done like this:
<my-component data='myData'></my-component>
Where myData
is the data structure provided to our component so it can iterate over it and draw the chart.
render()
This function is called just after the component is instantiated or modified and is responsible for generating the html
tags that eventually will be rendered by the browser. Here we generate the html
schema of our component and we will include the SVG element that we will use to generate all the pie chart elements.
componentDidLoad()
This method is called once the elements are fully loaded preventing us from getting null references of the html elements of the component.
Logic associated with D3, which is for regenerating data structures and graphical elements, must be set inside this method so we can guarantee that we may reference the final html.
Element()
This decorator allows us access to the main component and thus iterate over its children html
elements. In particular, this is the reference that we would use to use select
function of D3 and obtain the SVG where we will inflate our chart. Due to the encapsulation of Stencil we will have to access through shadowRoot
:
select(this.element.shadowRoot.querySelectorAll(".chart")[0]);
Once we get the reference of the SVG element we may forget all about Stencil and start to think about D3 exclusively. So we add the script to generate the pie chart (or other) and this is it, we would get our webcomponent ready:
With the previous code we would get a chart like this:
You may find a full code example in this GitHub link.
Finally: Export and reuse everywhere
Once we get our chart ready to publish we just have to build it and use it in any other project that we may have. Fortunately, this process is so simple as checking package.json
file for setting project name, version number, license, description, etc.. and launch build
command:
npm run build
This will generate the WebComponent ready to distribute in the www/build
folder. To use it in any other project you will only have to publish it into your account of npm and enjoy all its features:
npm login
npm publish
Conclusion
Stencil allows creating a modular working environment, exportable and accessible for the main web development frameworks. This is a great opportunity to unify al graphical elements of multiple projects into one and standardize their use, code recycling, html, css, etc..
If you work in a development team that is in continuous contact with the UX/UI department Stencil is the perfect place to develop a sustainable Design System once for all and to make it easy for everyone.