createCube function for qlik-api
One of the more popular helper functions in the Capability API
is the createCube
method. This method allows you to create a
hypercube (table of data) using defined parameters, passing the
resulting data to the page to be used or presented outside of Qlik
visualizations. It accepted two parameters,
a hypercube definition, and a function to call every time the
layout of the hypercube changes, also known as a callback function.
The createCube function
You can emulate and support your own createCube
function in qlik-api
.
Here’s a prototype for createCube
and an example in practice.
// createCube accepts a hypercube definition and a function definition// to be called each time the `changed` event fires on the hypercube// object.async function createCube(hyperCubeDef, callback) { // Gets the qix doc reference to the app from being added to doc prototype const app = this;
// okFunc checks for existence of a supplied callback function. // invokes callback function or empty function. const okFunc = await callback ? async function(data) { await callback(data, app); } : function() { };
// Create a session object from the supplied hypercube definition. const theData = await app.createSessionObject(hyperCubeDef); let dataLayout;
// When the object changes, get the layout of the updated object // and invoke the supplied callback function. theData.on("changed", async () => { dataLayout = await theData.getLayout(); await okFunc(dataLayout); return theData; });
return theData;}
// Export the function so it can be added to the doc prototype.export { createCube };
Example hypercube definition
Hypercube definition
const cubeDef = { qInfo: { qId: 'sessionChart', qType: 'qHyperCubeDef' }, qHyperCubeDef: { qDimensions: [ { qLibraryId: 'FFQHMq', }, { qLibraryId: 'KFmTudV', } ], qMeasures: [ { qDef: { qDef: "=SUM(Sales)", qLabel: "Total Sales" }, }, ], qInitialDataFetch: [ { qLeft: 0, qTop: 0, qHeight: 100, qWidth: 3, }, ], }, };
Using createCube with qlik-api
import { auth, qix } from "https://cdn.jsdelivr.net/npm/@qlik/api/index.js";import { createCube } from "./createCube.js";
// Replace with your host configurationauth.setDefaultHostConfig({...});
// Set the appId, open a session, and get the doc.const appId = "6b410f36-cb58-4bce-8e6f-a37220bfd437";const app = await qix.openAppSession(appId).getDoc();
// Add the createCube function to the doc reference.// app.createCube is like adding a prototype method.app.createCube = createCube;const myCube = await app.createCube(cubeDef, function(cubeData) { // console out the first page of the hypercube. console.log(cubeData.qHyperCube.qDataPages[0].qMatrix);});
// You can always get the layout of the hypercube you created// by calling a getLayout() function on it. This is because// createCube returns the session object created in the method.
let dataLayout = await myCube.getLayout();
Using createCube with qlik-embed
<script type="module"> import { createCube } from "./createCube.js"; const embeddedViz = document.getElementById("visualization"); const refApi = embeddedViz.getRefApi; const app = refApi.getDoc();
app.createCube = createCube;
const myCube = await app.createCube(cubeDef, function(cubeData) { // console out the first page of the hypercube. console.log(cubeData.qHyperCube.qDataPages[0].qMatrix); });
// You can always get the layout of the hypercube you created // by calling a getLayout() function on it. This is because // createCube returns the session object created in the method.
let dataLayout = await myCube.getLayout();</script>
Next steps
One of the main use cases for using the createCube
function
is to create a table using plain html
and have it update
automatically.
Here’s some example code using the createCube
function to
create and update an html
table dynamically.
import { auth, qix } from "https://cdn.jsdelivr.net/npm/@qlik/api/index.js";import { createCube } from "./createCube.js";
// Set up your host configuration.auth.setDefaultHostConfig({ ...});
// Supply the app Id with the data you want to connect to.const appId = "<app-id>";const app = await qix.openAppSession(appId).getDoc();
// Add your hypercube definition.const cubeDef = { //Add your hypercube definition here };
// Add createCube to the app reference.app.createCube = createCube;
// Create the hypercube session object by supplying the hypercube// definition and the callback function. The callback function// will update the hypercube layout on change events and call// the paintChart function to refresh the html table.const myCube = await app.createCube(cubeDef, function(cubeData) { paintChart(cubeData.qHyperCube.qDataPages[0].qMatrix, table, tBody);});
// In this example, calling a getLayout request one time// to get the columns and build the base table structure.// You have flexibility to make this better so go for it!let dataLayout = await myCube.getLayout();
// The html used in the example has a <div/> element// named chart-data. The table will be appended to this// element.let container = document.getElementById("chart-data");let table = document.createElement("table");
// This section builds out the table headers by getting// the columns from the dataLayout variable. Depending// on your hypercube, you will need to adjust the code.let cols = [dataLayout.qHyperCube.qDimensionInfo[0].title, dataLayout.qHyperCube.qDimensionInfo[1].title, dataLayout.qHyperCube.qMeasureInfo[0].title];let thead = document.createElement("thead");let tr = document.createElement("tr");cols.forEach((item) => { let th = document.createElement("th"); th.textContent = item; tr.appendChild(th);});thead.appendChild(tr);table.appendChild(thead);let tBody = document.createElement("tbody");table.appendChild(tBody);container.appendChild(table);
// After the table is set up, call the paintChart function// to populate the data the first time the page renders.paintChart(dataLayout.qHyperCube.qDataPages[0].qMatrix, table, tBody);
// The paintChart function loops through the hypercube data// and updates the rows of the table body to reflect the current// hypercube layout.
function paintChart(theCube, table, tBody) { let newTBody = document.createElement("tbody"); theCube.forEach((item) => { let tr = document.createElement("tr"); let vals = Object.values(item); vals.forEach((elem) => { let td = document.createElement("td"); td.textContent = elem.qText; tr.appendChild(td); }); newTBody.appendChild(tr); }); if (tBody != null) { table.replaceChild(newTBody, table.tBodies[0]); } else { table.appendChild(newTBody); }}