Qlik Community

Ask a Question

Qlik Design Blog

All about product and Qlik solutions: scripting, data modeling, visual design, extensions, best practices, etc.

Announcements
Join us at the Cloud Data and Analytics Tour! REGISTER TODAY
Dipankar_Mazumdar

Modern Embedded Analytics solutions using Qlik offers a stack of open-source libraries to build customized analytical platforms backed up with the robustness of Qlik’s Associative Engine. These new mediums facilitates communication with the Engine and provides the flexibility to develop your own client and services or to integrate visualizations and mashups. Historically, Capability APIs have been extensively used to build mashups and perform application related operations. An alternative offering to Capability API-based operations is Nebula.js and Enigma.js.

To clarify the use of each of these libraries, let’s breakdown their functionalities in a simplistic way to help the developer community to get started with them.

bed_0-1619007352807.png

 

In this tutorial, we are going to focus on a user scenario that involves applying both Enigma.js and Nebula.js. This way we can have a fair idea of their applications and get started with their immense capabilities. 

User scenario: A company needs to build its own analytic solution while being able to leverage data from Qlik’s Associative engine and embed a couple of visualizations. The overall goal is to have some buttons in their webpage that would control the ‘dimensions’, allowing them to render the visualizations based on the buttons’ click. They have approached a similar type of situation in the native Qlik Sense using ‘variables’ and they would like the same capability in their own web solution.

Solution: Since the company has taken advantage of ‘variables’ in the native QS, a similar approach for their web solution using the two libraries would be the following:

  1. Create a Mashup template using Nebula.js.
  2. Fetch the variable and its definition from QIX using Enigma.js.
  3. Load and register QS objects(action-button, charts) using Nebula’s stardust package.
  4. Consume the fetched variable in the ‘action-button’ and render.
  5. Integrate all the required visualizations from QS in the mashup.

Let’s go through each of the steps in detail to understand how we can implement them -

Step 1 — Creating Mashup template: In this tutorial, the focus is not on developing mashups but to implement the user scenario. A very simple tutorial to get started with developing mashups is on the official Qlik Developer site. Link: https://qlik.dev/tutorials/build-a-simple-mashup-using-nebulajs

Using the command line interface, we create a web project that has the following structure -

/src

  • configure.js - Initial configuration of nebula.js
  • connect.js - Connection setup with enigma.js
  • index.html - A html page template
  • index.js - Connect and visualize

 

Step 2 — Fetch the variable using Enigma.js: Like I discussed, Enigma.js allows us to communicate with the QIX engine and enables us to perform CRUD(create, read, update, delete) operations on QS apps and their entities. Since in this case, our target is to read a variable named ‘vChangeField’ from a QS app, we first create an object with list definition like below:

 

 const variableListProps = {
    qInfo: {
      qId: "VariableList",
      qType: "VariableList",
    },
    qVariableListDef: {
      qType: "variable",
      qData: {
        tags: "/tags",
        name: "/",
      },
    },
  };

 

In order to create the list object that we have defined, we use the createSessionObject() method provided by Enigma.js. After that, the properties of the object, including dynamic properties are retrieved using the getLayout() function and passed on to a passVariable(layout) like below:

 

 const variableListModel = await app
    .createSessionObject(variableListProps)
    .then((model) => model);

  variableListModel.getLayout().then((layout) => {
    passVariable(layout);
  });

 

Now that we have the object properties in the layout, the next step is to retrieve the ‘variable’ inside our function passVariable() and use it on the ‘action-button’ that we will create for our mashup.

 

 function passVariable(layout) {
    const {
      qVariableList: { qItems: data },
    } = layout;
    var pass_need = data[1].qName;
 }

 

So, we finally have our desired variable stored in ‘pass_need’. This is all we had to do to fetch our variable using Enigma.js.

Step 3 — Load and register ‘action-button’ and other charts: Our next step is to load the QS objects, i.e., ‘action-button’ and ‘combo’ and ‘bar’ charts required as part of this use case in our mashup and, to do that we will leverage Nebula.js. So, let’s go to the template defined in the configure.js file where we can see the following:

 

import { embed } from '@nebula.js/stardust';

import barchart from '@nebula.js/sn-bar-chart';

const n = embed.createConfiguration({
  context: {
    theme: 'light',
    language: 'en-US',
  },
  types: [
    {
      name: 'barchart',
      load: () => Promise.resolve(barchart),
    },
  ],
});

export default n;

 

In this file, we have the initial configuration needed from Nebula.js perspective. First, an embedclass is imported from the ‘@nebula.js/stardust’ package and then using the Configuration object, we define the guidelines for our visualization and website. We also see that a bar-chart module is loaded from the package and then registered under types. This is what needs to be done to render our QS visualizations.

For this use case, we need three action buttons , and one bar and one combo chart in our mashup. So, let’s load and register these three visualization components as shown in the snippet below:

 

import { embed } from '@nebula.js/stardust';

import barchart from '@nebula.js/sn-bar-chart';

import actionButton from '@nebula.js/sn-action-button';

import combochart from '@nebula.js/sn-combo-chart';

const n = embed.createConfiguration({
  context: {
    theme: 'dark',
    language: 'en-US',
  },
  types: [
    {
      name: 'barchart',
      load: () => Promise.resolve(barchart),
    },

    {
      name: 'action-button',
      load: () => Promise.resolve(actionButton),
    },

    {
      name: 'combochart',
      load: () => Promise.resolve(combochart),
    },

  ],
});

export default n;

 

 

Step 4 — Create the action-buttons and render: In our previous step, we loaded and registered the three types of visual components we need as part of this mashup. Now, we need to use the fetched variable ‘vChangeField’ in the three action-buttons and render them. First, let’s create a new embed instance using the Enigma app in the index.js file and then render the action-buttons using the render function. This function renders a visualization into an HTMLElement.

 

const n = embed(app);

function passVariable(layout) {
   n.render({
      type: "action-button",
      element: document.querySelector(".object_new"),
      properties: {
        actions: [
          {
            actionType: "setVariable",
            variable: pass_need,
            value: "Decade",
          },
        ],
        style: {
          label: "By Decade",
          font: {
            size: 0.7,
            style: {
              italic: true,
            },
          },
          background: {
            color: "Grey",
          },
          border: {
            useBorder: true,
            radius: 0.25,
            width: 0.1,
            color: "Grey",
          },
          icon: {},
        },
      },
    }),
      n.render({
        type: "action-button",
        element: document.querySelector(".object_new"),
        properties: {
          actions: [
            {
              actionType: "setVariable",
              variable: pass_need,
              value: "Actor",
            },
          ],
          style: {
            label: "By Actor",
            font: {
              size: 0.7,
              style: {
                italic: true,
              },
            },
            background: {
              color: "Grey",
            },
            border: {
              useBorder: true,
              radius: 0.25,
              width: 0.1,
              color: "Grey",
            },
            icon: {},
          },
        },
      }),
      n.render({
        type: "action-button",
        element: document.querySelector(".object_new"),
        properties: {
          actions: [
            {
              actionType: "setVariable",
              variable: pass_need,
              value: "Director",
            },
          ],
          style: {
            label: "By Director",
            font: {
              size: 0.7,
              style: {
                italic: true,
              },
            },
            background: {
              color: "Grey",
            },
            border: {
              useBorder: true,
              radius: 0.25,
              width: 0.1,
              color: "Grey",
            },
            icon: {},
          },
        },
      });
}

 

While creating the three action-buttons, we also need to specify their properties under properties as seen above. One of the important things to consider when defining the properties for an ‘action-button’ is what action do we want this button to execute on click. This is very similar to what we do non-programmatically in the native Qlik Sense app with action buttons. For this use case, we want these buttons to set a variable when clicked. So, under actions we set the actionType: “setVariable” . The next step is to pass the variable that we have retrieved using Enigma.js. In Step 2, we stored the variable in ‘pass_need’. So, we will pass this to the variable: pass_need property. We also, set a default value for each variable using the property value: “Director”.

Step 5 — Integrate all the visualizations: Our final step is to bring all QS objects together in the mashup. We have already created and rendered the action buttons and, since we already have the combo and bar-chart in our QS app, we don’t need to create them but we will just retrieve them using their object IDs like the snippet below:

 

n.render({
    element: document.querySelector(".object"),
    id: "QVngr", //object ID of combo-chart
  }),
    n.render({
      element: document.querySelector(".object"),
      id: "JbtsBVB", //object ID of bar-chart
    });
}

 

 

Mashup in action:

bed_1-1619007883514.gif

 

As we can see, the rendering of the charts changes on the basis of the ‘button’ we click. The button leverages the ‘variable’ defined in our Qlik Sense application. This tutorial presents an alternative to the Variable API used inherently for performing CRUD operations with variables. It also demonstrates the usefulness of Nebula and Enigma.js frameworks for developing modern embedded analytic solutions.

The Source code for this mashup can be found here: https://github.com/dipankarqlik/Variable_Enigma