Qlik Community

Ask a Question

Qlik Design Blog

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

Announcements
May 18th, Changes to the way you login: using email vs. username. READ DETAILS/WATCH VIDEO
Francis_Kabinoff
Employee
Employee

Let’s take a look at how the visualization lifecycles (creating/updating/destroying visualizations) in the Visualization API and nebula.js currently compare to each other.

Let’s take a look at how the visualization lifecycles (creating/updating/destroying visualizations) in the Visualization API and nebula.js currently compare to each other.

 

Creating

Both the Visualization API and nebula.js are capable of both rendering existing objects and creating visualizations on-the-fly. The Visualization API  method for rendering an existing object starts with its get method, which returns an instance of the QVisualization class. Then the show method of the QVisualization class is used to render the visualization. Creating visualizations on-the-fly with the Visualization API starts with the create method, which, like the get method, returns an instance of the QVisualization class. And again the show method is used to render the visualization. They looks like this.

 

 

 

// The Capability APIs resources must first be loaded

// Get an existing object and render it with the Visualization API
qlik.app.visualization.get(objectId).then(function(vis) { 
  vis.show('elementId'); 
});

// Create a visualization on-the-fly with the Visualization API
qlik.app.visualization.create(type, cols, options).then(function(vis) { 
  vis.show('elementId'); 
});

 

 

 

 

nebula.js is also capable of both rendering existing objects and creating visualizations on-the-fly. With nebula.js, you first create an embed instance and then use the render function of the embed instance to do both. They look like this.

 

 

 

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

// Create an embed instance with nebula.js
const n = embed(app);

// Render an existing object with nebula.js
n.render({
  element: el,
  id: 'abcdef'
});

// Render an object on-the-fly with nebula.js
n.render({
  element: el,
  type: 'barchart',
  fields: ['Product', { qLibraryId: 'u378hn', type: 'measure' }]
});

 

 

 

nebula.js has the advantage of not having to load the resources for the Capability APIs, which includes require.js, jquery, Angular.js, and CSS code. But not all charts may be supported yet in nebula.js. You can check the list of currently supported charts in nebula.js. Of course, you can always create your own chart type with nebula.js too! Then you can register it as an extension, as demonstrated @ Build a HelloWorld extension using nebula.js, or just register it as a chart type and create the visualization on the fly in nebula.js.

 

Updating

The current functionality between the Visualization API and nebula.js is a bit different from each other as of today. While a Visualization API visualization has the setOptions method available which allows for patching the underlying hypercube and changing various options for the existing visualization, there is no way to change it to a different type of visualization. Conversely, while nebula.js currently has no supported method to patch the underlying hypercube, the experimental convertTo method can be used to change the type of visualization. Let's take a look at an example of both.

 

 

 

// Set new options with the Visualization API
app.visualization.get('xGhjKl').then(function(vis){
  vis.setOptions({title:"Now improved"});
});

// Convert to a different type of visualization with nebula.js
(async () => {
  const viz = await embed(app).render({
    element,
    id: 'abc'
  });
  viz.convertTo('table');
})();

 

 

 

 Note that I used a promise chain with the Visualization API example, but async/await with nebula.js. There's no reason for the difference except when I use the Capability APIs it tends to be in older projects where promise chains were the pattern to use with promises, while I tend to use nebula.js in newer projects where I prefer async/await.

Now, even though there's no method on the visualization handle returned by the render function in nebula.js, it can be done using enigma.js. Since the render function returns the ID of the object, we can use enigma.js to get a handle for the object and then use the applyPatches method. That looks like this.

 

 

// Render viz with nebula.js, then use the id of the session object
// returned with the viz handle to get a handle of the qlik object
// and patch it
(async () => {
  const viz = await embed(app).render({
    element,
    id: 'abc'
  });
  const obj = await app.getObject(viz.id);
  obj.applyPatches([
    qOp: 'replace',
    qPath: '/qHyperCubeDef/qDimensions/0/qDef/qFieldDefs/0',
    qValue: JSON.stringify('[Field]')
  ]);
})();

 

 

And with the object handle, not only can you apply patches such as shown here, but you can use any of the methods available to the GenericObject class of the Qlik Engine JSON API.

 

Destroying

Both the Visualization API and nebula.js, whether you are embedding an existing visualization or creating a visualization on-the-fly, will create a new Qlik session object. And, especially in a larger app, if you don't clean up, you'll end up with a whole lot of session objects and performance will suffer. Therefore, when you no longer need to render the visualization, whether using the Visualization API or nebula.js, you should destroy it. If you then need to render it later, you can just render it again. The Visualization API uses the close method and nebula.js uses the aptly named destroy method to destroy a visualization. Let's take a look at destroying visualizations with both the Visualization API and nebula.js.

 

 

 

// Close a visualization with the Visualization API
var visRef;
app.visualization.get('xGhjKl').then(function(vis){
  visRef = vis;
  vis.setOptions({title:"Now improved"});
});
if (visRef) { visRef.close(); }

// Destroy a visualization with nebula.js
(async () => {
  const viz = await embed(app).render({
    element,
    id: 'abc'
  });
  viz.destroy();
})();

 

 

 

Notice again, the difference in how promises are handled between the two examples. No reason except it's what I prefer based on the type of web app I'd expect to encounter each one.

 

Now that we've taken a look at the lifecycle of visualizations in both the Visualization API and nebula.js, tell me what you think. Are you still using the Capability API? Are you already using nebula.js? What kind of things do you want to know how to do with nebula.js? Let me know!