One of the more advanced feature in QlikView is alternate state. It alllows you to have several different selections active at the same time. With set analysis expressions you can then combine your selection sets to gain valuable insights.
While alternate states are not exposed in the built-in Qlik Sense client, you can easily add them to your custom extension with just a few lines of code. Let’s see how.
Step 1: add a property panel field
The qStateName property already exists (check the Qix Engine API), so a first step is to map it to the property panel. Lets create a new section under “Addons”:
This assumes a HyperCube, $ is the default state which is always there. This is already enough for alternate state to work in your extension. If you enter a valid alternate state name in the property panel your extension will be connected to it. Problem is there has to be an alternate state in the app, and you need to know it’s name. Lets do something about that.
Step 2: add a listbox with existing alternate states.
Lets convert our property panel to a dropdown list, where the app developer can choose what state the object should be connected to. We do this by setting the component to ‘dropdown’ and adding a function to return the options:
Alternate states ar listed in the app layout structure, so we need to get the app layout and format the states in the format the property panel dropdown wants. The default state ‘$’ is not in the list, so we need to add that ourselves. For this to work you need to have the qlik module available in your extension.
Now you will have a dropdown list in your extension property panel, something like this:
Still doesn’t look much, does it… But it does it’s job. Now we just need a way to create those alternate states.
Step 3:Creating the alternate states
Well, actually you need to do this first. But there are different ways to achieve this:
there are extensions for this
you could do it in Engine API explorer, since its really a one-time thing
or, you could add it to the property panel.
The property panel is not really meant for this, since we are not updating the object properties, but the app properties, but still it’s pretty easy to do. You can add something like this to the property panel:
It’s really not more complicated than that. You will get an inputfield in the propertypanel. If the user writes anything in that field, an alternate state will be created. It will then show up in the listbox, so you can use it in your extension.
It’s really not at all difficult to add alternate state support to your extension. Probably you should do something to show the user that this chart belongs to an alternate state: you can use the header for that, or add some styling or an icon for charts that are in another state. I’ll leave that for you.
Probably the most important object you can have in your Generic Object is the HyperCube. It is what is used in most charts and is the way to tap into engine associative logic and calculation engine. Hypercubes reflect the users selections and calculations will be made on the current selections.
The hypercube properties are in a structure called qHyperCubeDef. A common setup is the one from the peoplechart extension example we have seen before:
This will create a hypercube definition with an empty array of dimensions and an empty array of measures. It will also tell engine to include 2 columns (probably 1 dimension and 1 measure) and 50 rows of data with the initial fetch of data, that is in the reply to the getLayout call. This works because the user can add dimensions and measures using the property panel, which is defined like this:
In a mashup you would in most cases need to list the dimensions and measures you want, something like this (taken from my angular-based mashup example available on GitHub:
This will create a hypercube with eight dimensions and no measures, tell engine that we want all eight columns and 400 rows in the initial fetch, set some other properties and define a call back function called setCases (not included above) that will be called every time the hypercube data has changed.
While it is possible to have a hypercube without dimensions, you probably could use a simple expression instead in most cases. So you normally would have a dimension array. This array should contain one or more NxDimenion object(found here, you need to scroll down a bit). There are two alternatives:
use a predefined dimension from the list of dimensions. If you do that you should set the qLibraryId to the id of the dimension you want to use.
use a dimension that is defined only in this dimension array. In that case you should set qDef to an object that in turn contains the dimension definition. Note that qFieldDefs is actually an array, and so can contain multiple definitions. You can actually define a cyclic group here, though I have never seen it used and don’t think it is supported in the client.
Whether you use a predefined dimension or a locally defined dimension there are some additional properties that might be useful. The most complicated is qOtherTotalSpec, which you can use to limit your hypercube to the top 10 values, or bottom 10 etc.
The measures array works much like the dimensions array. It also has two alternatives: referring to a predefined mease with the qLibraryId field or defining the expression in a qDef structure. Note that the measure qDef structure is not the same as the dimension qDef structure: instead of the qFieldDefs array it holds just a string field (also named qDef) with the actual expression.
Make sure you get some rows
To make sure you actually get some data in your hypercube you need to set the qInitialDataFetch property. This is actually an array, but I have never seen an example with more than one entry in the array. You should set qWidth to the number of columns (that is dimensions plus measures) in your cube and qHeight to the number of rows you need for the initial rendering of your cube.
If you do not set this property, the default is 0 rows and 0 columns, so you will get no data. A very common problem in extension development is that you add dimensions or measures and forget to update the qWidth parameter, so you do not get any values for your measures. Also rememeber that what you specify in your extension is the initial properties, so when you change your code, the objects already created will not change. A way to avoid this problem is to set qWidth to something high (10, for example) since a value that is higher than the actual number of columns will work and get you all columns.
Create a hypercube in the mashup editor
A feature not well known in Qlik Sense mashup editor is that it can help you create a hypercube. In the left column of the editor there is a button labeled ‘Add hypercube’. Select the app you want to work with and click it, and you will get a popup, something like this:
When you click the ‘Add’ button, it will create a createCube call for you, with most of the properties filled in:
Even if you don not use the mashup editor for creating your mashup, this feature can be useful.