Migrate an existing Visualization extension to Nebula.js framework
To demonstrate the overall migration process, I will take an existing visualization extension that I have developed in the past using the Extension API. The extension is a Scatter-Pie plot that allows us to visualize each scatter plot’s bubble as a pie-chart to understand the Sales-Profit correlation for the three categories state-wise as shown below:
Let us try to recreate the exact same visualization by leveraging the novel Nebula.js framework.
Step 1: Create a Nebula project structure. The first step is to get all the files required as part of developing the extension. We can use the Nebula.js CLI like below and structure the project.
npx @nebula.js/cli create hello --picasso none
Executing the above command, gives us the three required files.
Step 2: Starting the local development server. One of the advantages of using the Nebula.js framework is that it comes with a local development server that allows developers to see their output as they code. To start the server, execute the following command.
npm run start
Now, we will need to connect to Qlik’s Associative Engine using the WebSocket protocol. Once we establish a connection, we will be presented with the list of apps to test our visualization in the Developer UI.
The only thing that we do differently here in Nebula is to add the
/qHyperCubeDef as a data target in
data.js like this:
Step 4: Import packages. Nebula.js is built on the concept of custom hooks. If you do not know what hooks are, this tutorial will give you a high-level idea of how to leverage them in terms of Nebula. As per the Getting started with Nebula extension tutorial, we will need to import two essential packages to access the Qlik Sense object’s layout and render the data. They are useLayout and useEffect . Also, since our visualization is built using D3.js, we will need to install D3.js in our NodeJS environment and import the package for D3 using the commands below.
Install D3 by running
npm install d3 --save
Import D3 to
index.js by adding
import * as d3 from d3
Now, let us understand what we did differently here in the Nebula.js framework as compared to the Extension API.
As we can see from the above comparative analysis, the primary difference is that the Extension API uses RequireJS to load resources asynchronously and has a jQuery wrapper around the HTML element. In the Nebula.js framework, we eliminate all these dependencies, thereby making it framework agnostic and faster.
Step 5: Code Logic. Our most important goal is to develop the main functionality of the extension. Again, the whole idea here is to replicate the exact visualization developed using Extension API without investing additional time in rewriting the source code. The entry point for the extension’s code is the index.js file, and currently, it looks like below with all the necessary packages.
Now, let’s take a look at our current extension’s JS code.
To render the visualization with an HTML element, we take advantage of the paint($element, layout) method where $element is a jQuery wrapper containing the HTML element and layout presents the data and properties for the visualization. This method is called every time the visualization is rendered. So, do we have a similar approach in the Nebula.js framework? The answer is Yes!
If we go back to our index.js file, we notice a function supernova( ) that consists of the component( ) method, which is where all the rendering takes place. To render something, we will need to access the DOM element the visualization is assigned to, and to do so, we need to use the useElement method. Also, as I mentioned in Step 4, to access the QS object’s layout and bind the data, we need to use the useLayout and useEffect methods. These three methods are all we need to migrate our current code to the newer framework successfully.
After copying the current code and aligning it to Nebula’s programming standard, this is what we get.
We see that most of the code lines are similar to what we had in our Extension API. The only difference lies in the way we interact with the three methods here in Nebula.js. In the end, the viz( ) method is called within the component( ) function, and that is where our D3.js code for the visualization is. Again, this is similar to what we did in the Extension API. That is all we needed to do from a code perspective.
Firstly, since Nebula runs in a NodeJS environment, we can easily bundle everything and distribute the visualization as an NPM package using -
npm run build
Secondly, to deploy the extension to a QS environment, we use the below command below, which generates all files into the folder
/hello-ext, that you can then use as an extension in QS.
npm run sense
Now that we know about the resources required to migrate our existing extensions to the Nebula.js framework, let’s recap the potential benefits of the new SDK.
- Nebula.js is modular and allows developers greater flexibility in programming and code maintenance.
- It comes with a local development server to visualize the output as we code.
- Modern framework with no dependency on module loaders such as RequireJS or wrappers like jQuery.
- Available as an NPM package and hence very easy to get started with.
- Faster build and deployment; visualizations can be distributed as NPM packages.
- Way forward — support, etc.
This brings an end to the post, and hopefully, this will serves as an initial guide for developers and organizations planning to migrate their existing visualizations to the Nebula.js framework. For folks who want to get started with Nebula or build advanced visual representations using the SDK, here is a list of accumulated resources -
- Building a Hello world extension using Nebula
- Why should we stop using Capability APIs?
- Building an advanced visualization extension using Nebula.js and 3rd party libs such as D3.js
- Dealing with variables in a Mashup using Nebula.js & Enigma.js (alternative to Variable API)
Want to learn more about what we do in Qlik with Visual Analytics, Machine Learning and Embedded Analytics? Follow me on my LinkedIn — https://www.linkedin.com/in/dipankar-mazumdar/