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 configuration
auth.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);
}
}