A look at filters in Qlik Sense charts

One of the recent new features in Qlik Sense is the ability to add filters to charts, filters that applies only to the chart they are included in, not other charts. So far this is only available n Qlik Sense Clod. (Help is available here)

It has always been possible to filter data in a chart, but setting it up has been more complicated. The new feature makes it much easier and more straightforward, so it is surely a feature that will be welcomed.

Setting it up

To try this I’ll use a copy of the Demo App – Beginner’s tutorial that’s available in QlikSense Cloud If you want to follow along, open it in Qlik Sense Cloud and then make a copy of the sheet ‘ Product details’. Then click on ‘Edit sheet’ in your new sheet.

The filter option is only available in the new authoring mode, so make sure you’r not in the old one (called ‘Advanced options’). I’ll be using the chart ‘Sales and margin by Product Group’ but since that is actually a master object, and you can’t use the new authoring mode on master objects, I’ll firts have to unlink it, to make it no longer a master object. Once that is done, we’re ready to go.

This is what the sheet looks like when we start

Adding a filter

Filters are based on Qlik set expressions, but do not fear, there is help available to create the expressions. To add filters you use this little area:

First step is to enter the field namn (no, you cannot use dimensions). Do that, either by clicking Add and then searching for the field namn or by dragging and dropping the ‘Region’ field and you get a dialog like this:

Selecting filter values

Just select one or more regions and we are done:

Chart with filter

To verify that it works, end edit mode and make some selections in the region field. Notice how the values in the other charts change, but not the values in our filtered chart, they will still be showing the values in the reion(s) we set in the filter (in my case Nordic). So far so good.

What does the filter affect??

But exactly what does the filter affect? It surely affects the data in the chart itself, but what about other expressions, like dynamic titles etc? Let’s try. Change the title of the chart to (you will probably need Advancd options for this):

=’Sales and Margin by Product Group. Total: ‘ & Sum(Sales)

And now you will have a sum added to your chart title. Switch to analysis mode again, and make some selections in the Region field. Notice that the sum in the title changes, so the filter does not affect the title.

The filter will only affect chart data, not dynamic titles etc. That’s important to be aware of if you are using dynamic titles.

Chart with filter and dynamic title. The filter does not affect the title.

Displaying the filter to users

As you might have noticed Qlik Sense shows the filter at the bottom of the visualization. That works pretty well in this case, but in many Qlik data models you have flags with name that are not so user friendly, or you might have fieldnames with prefixes or more cmplicated filters. If that is the case you can enter your own describing text as a footnote to the chart, like this:

Adding footnote in property panel

And you will get your own text instead of the default one:

Custom filter description in the footnote

Behind the scenes

If you take a look at the properties of your visualization (I use my own Chrome extension for this) you can find your filters in their own structure:

Filters structure in object properties

Using this structure Qlik Sense then generates the actual set expression (qContextSetExpression) that is used:

Accessing system data and variables in a Qlik Sense extension

Sometimes when you are building a Qlik Sense extension you need to get access to system data. This is espescially true if you are trying to build something a bit more generic. Perhaps you need a list of fields, or dimensions, or measures. Or you need to work with variables.

If you are new to Qlik Sense development you might look in the API documentation for methods to get the data you need. Don’t do that!! Qlik Sense extension model is based on the idea that you use one Generic Object, described in the extensions initialProperties, and modified by the user in the property panel, and possibly programmatically (but that’s really advanced). So while using the API methods to get additonal data is the approach to use in mashups or Web apps that access Qlik data, you should avoid using them in a masup.

Why you shouldn’t

If you do use these api calls in your extension, you will get problems:

  • you might easily get a memory leak, or a ‘Generic Object leak’, where you create lots of Generic Objects
  • you can easily lose contral of all callback functions running when the generic objects are revalidated
  • if the user makes a snapshot, the API calls will access the latest version of the data, not the one in the snapshot and possibly give the wrong data
  • if the user tries to export your extension to PDF or Excel it might break, since the service responsible for those export does not have access to live data, only to the snapshot

If you absolutely must use these calls, you should at least turn export to PDF and Excel of and not allow snapshots of your extension.

What you should do instead

Luckily there are alternatives. These API calls all create Generic Objects, but since the Generic Object is a very flexible structure, you can actually configure the Generic Object behind your extension to provide the data you need. Here is a little table of what you could use:

You needDo not use API callInstead add to initialProperties
List of fieldsapp.getList("FieldList")qFieldListDef
List of measuresapp.getList("MeasureList")qMeasureListDef
List of dimensionsapp.getList("DimensionList")qDimensionListDef
List of variablesapp.getList("VariableList")qVariableListDef
Variable valueapp.variable.getContent(..)qStringExpression or
qValueExpression

You find a working example of this in my syslist extension just don’t use it, it’s meant as examples of how to get the data and doesn’t really do anything useful. But do grab the initialProperties part you need for your extension.

It looks like this:

When should you use these API calls

Well, no rule without an exception. While you should avoid using these calls in the API for the rendering part of your extension, you should use them in your property panel, if you for example need to provide a list of fields to the user. And in a mashup, they are definitely very useful. And the API has other calls, which you might want to use, but that vill mainly be when the user does something, like clicking a button etc.

Qlik Sense Generic Object IV: The lists

A Qlik Sense Generic Object can also be used to list objects in the Qlik Sense app to which it belongs. You can use it to list things like:

  • fields
  • dimensions
  • measures
  • bookmarks
  • snapshots
  • media (that is images controlled by Qlik Sense)
  • sheets
  • master objects
  • variables
  • stories

The javascript APIs provide the app.getList method, which is a wrapper that helps you get theses lists. It will create a session object for you with the list you are requesting, get that actual data in the list and call your callback function once the data is available.

List are live – your callbacks might be called several times

Just like with other Generic Objects the data might be invalidated. If you are using the javascript APIs it will then be automatically revalidated and your callback function will be called again, so you should be prepared that your callback might be called multiple times. But unlike the Hypercube and List Object the lists are not affected by the users selections. Instead they will be invalidated when the underlying data changes:

  • if the user adds a bookmark, you will get a new bookmarklist
  • if the user adds a measure, you will get a new measurelist
  • if the user adds a dimension, you will get a new dimensionlist
  • etc….

Configure the data you get in your list

The data you get in your lists is configurable. If you use the API method, you will get a default set of fields for each item in the list, but you can set the list up to suite your needs.

As an example, if you use the api method getList(‘measure’, callback), you will get a list where records look like this:

The first and second part, qInfo and qMeta, will always be there. They contain the id to use when refering to this measure and title and description use ful in a list of measures. The third part however, qData, is configurable. The default configuration just gives you tags and title one more time, but if you instead want more data about the measure, you can use your own measure list definition like this:

Under qData you provide your own mapping of the properties you want. In this case I have just specified that I want everything under qMeasure included. You can also specify individual fields.

And get output that includes more data for the measures:

And the same goes for the other lists, you can supply your own definitions and get more data included.

Qlik Sense Generic Object III: Listboxes

SWhile the HyperCube is the main object for calculating data the ListboxObject is a way to list available values for a field. Its the object behind the listboxes in the Filter Panel. It is also the object used for the listboxes that are created when you click on a field in the selection toolbar.

An example setup from the horizontal listbox extension example, included with the Qlik Sense installation:

This contains defaults for most of the parameters, except the actual field, which the user selects in the property panel, which looks like this:

As you can see the Listbox has either a predefined measure from the library, in which case qListObjectDef.qLibraryId will contain the id of the measure (some UID string) or it has a field name, which will be in the array qListObjectDef.qDef.qFieldDefs at the first position. You don’t really have to bother about which one the user selects to use, the ListboxObject will work the same anyhow.

Frequencies and sort order

There are also some other properties in the ListboxObject that are well known to QlikView users. The frequence mode gives you some additional info on the frequency of the respective values in the ListboxObject. Look to horizontal listbox extension for an example. There is also the qSortCriterias array, which allows you to specify the sort order. The default is to have the selected values first, but you might want to for example keep months order from January to December irrespective of which month is selected.

Mashup editor – even more properties

Like with the Hypercube, you can also build a ListboxObject in the mashup editor. The tool to do this looks like this:

As you can see, you also get the option to include expressions in your listbox, usable if you want to make some calculations for each value in the list. The mashup editor will create a ListboxObject for you like this:

The expressions are added to the ListboxObject in the qExpressions array. In this example I have used predefined measures, but you can also use measures defined in the actual listbox object. The mashup editor includes a expression editor (actually the same used in the Qlik Sense client) to help you with this.

Qlik Sense Generic Object II: Hypercube properties

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.

Hypercube properties

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.

Defining dimensions

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.

Adding measures

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:

hypercubebuilder

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.

Qlik Sense Generic Object I: General

Getting data out of a Qlik Sense app is based on a concept called Generic Object. Behind all charts, tables and listboxes in Qlik Sense lies a generic object. Also behind many of the other things you see in the Qlik Sense client lies generic objects:

  • the selection toolbar
  • the panel on the left side of the page, with lists of dimensions, measures and master objects
  • the sheet is a generic object

The purpose of the Generic Object is to make it easier to make client-side changes without having to change the QIX engine. Since the Generic Object is very flexible, many client side changes do not require any changes to the engine.  This is in contrast to how it works in QlikView, where all charts have different server-side implementations and client and server code are tightly coupled. This is also a reason why extensions are so powerful in Qlik Sense: to the QIX engine there is really no difference between built-in visualizations and extensions, they are all represented with a Generic Object.

Properties and layout

When you create a Generic Object you define its properties. This is a JSON structure, which you can define yourself. An example (from the peoplechart extension example):

There are two kind of properties:

  • user defined. Qlik only persists those and include them as-is in the layout, it is up to your code to use them for something
  • defined by Qlik Engine. These are validated by the Engine, and replaced in Engine output, the layout, by the calculated counterparts.

All properties defined by Engine start with a q, so it is good programming practice to let your own properties start with some other letter. The properties defined by Engine are documented here and the corresponding out data is documented here. Note that properties defined by the Qlik Sense client(like title etc) do NOT start with a q, the QIX engine does not really know what these are used for.

But the parameters known by the QIX Engine will determine the engines calculation. In the output from engine, called layout (though it’s not really the layout of a Generic Object) the definition of those properties will be replaced by the results. A hypercube definition (qHyperCubeDef) will be replaced by a actual hypercube (qHyperCube) containing the results from the calculation.

Generic Object context

Generic objects are everywhere in Qlik Sense. If you are building an extension, you define your Generic Object structure in the initialProperties property. If you are using the mashup API, you create generic objects with the createGenericObject method or one of the wrappers around it (createCube, createList, getList). In both these cases the Qlik Sense client framework will automatically refresh the Generic object with new data when it is invalidated (by for example new selections). If you are working directly on the protocol level, you need to fetch they new data yourself.