A common mistake when you start with Qlik Sense extensions is to forget about setting Initial data fetch in your extension. Typically you would include something like this in the initialProperties of your extension:
That would work, and make sure your extension gets the 500 first rows of data in the layout provided to your paint method. But sometimes you want the app developer to be able to set the number of rows fetched. In that case you can simply add the qHeight parameter to the property panel like this:
And the result is a new section in the property panel, where the app developer can set the number of rows initially fetched.
When you work a lot with something you develop opinions about how things should be done. Here is my list, after two years as an independent contractor, mainly with Qlik Sense extensions and mashup, and of course based on my experience from Qlik.
1. Use version handling
There is no reason not to use version handling of your code. I use Git for everything, but if you are still using something else, that might be OK too. You probably should consider switching to Git, but as a developer that might be a decision taken over your head.
The benefits of using version control are enourmous. You can easily go back and find the reason behind a bug or the implementation behind that feature the customer now wants in another extension too. Invaluable!
You also should keep a version number in your qext file, and change it every time you deploy a new version. The main benefit of this is that you can see what version of your extension is in use in a Qlik Sense installation. I have described how to do this in a previous post.
2. Always test your extension in a browser
3. Stay in your sandbox
do not inject HTML elements outside of your own element
prefix your CSS rules so that it affects only the extension
avoid html id’s, since they must be unique within the page. If you must use one (really only when you use a library that needs an id) make sure they are unique for each extension instance (test with multiple instances of the same extension)
There are occasions when you need to break theses rules, but only do it when it’s need for your extension functions.
4. Use modern development tools
Pretty soon after you have started with extension development you will grow out of the Qlik Sense dev-hub extension editor. A modern, nodejs-based environment, with a good text editor gives you a lot of benefits, and works well with version handling software. I would recommend the following:
a good editor. I mostly use Visual Studio Code, but there are others that probably are just as good.
a CSS preprocessor like less helps you with prefixing css, add vendor prefixes etc
a lint tool, to find common errors an enforce good programming practices
5. Always keep your extension backwards compatible
After a while your users will most likely want more functionality in your extension. They might want more interactivity, more rendering options, perhaps support for more dimensions and measures. You will probably add new settings giving your extension more flexibility. You might also find that some of the stuff you originalyy programmed was not perfect (that happens to all of us..). But if you have deployed your extension to production, make sure that all your changes are backward compatible. If you don’t you will have huge problems when you deploy the new version, with breaking apps.
If you find it impossible to make your new extension backwards compatible you probably should not be making a new version, but a new extension, with a different name.
6. Base your rendering on only the layout
The model behind Qlik Sense extensions (and the built-in charts too, actually) is that the extension is based on a Generic Object, where you configure the Generic Object in the property panel and use the layout for rendering. Stick to that model, do not break it. If you need more data for your rendering, add it to the properties structure. Avoid:
creating HyperCubes and ListBox objects programatically, add them to initialProperties and the property panel instead
fetching variable values programatically, add expressions to the property structure instead (that also gives the app developers more options, like hard-coding values, or making them change automatically as selection state (or data) changes
It is however OK, even recommended, to call API methods for:
showing lists of available values in the property panel
making selections etc when the users clicks on buttons, menues or other parts of your UI
call the Engine API method doReload(). Use this in Qlik Sense desktop, since it’s the only method available.
use the repository call App reload optionally with the help of the callRepository method. This is of course only relevant in a server installation.
You’ll find code examples in my original post, and also how to know if you are running in server or desktop.
What happens when you use /app/reload ?
While this method works well in some scenarios, like when you just want to run one reload of an app ASAP, it has some limitations. Behind the scenes Qlik will create a very simple task for you, and try to start it immediately. The task will look like this:
Very basic, just an app, a name, an the default Task session timeout of a day (or 1440 minutes). No triggers, since the task is started by the REST call, no tags, no custom properties. And, perhaps most important, no retries. This means that if you create a series of reloads this way, most likely only the first few will succeed, the rest will fail since there is no engine instance available.
Another method to start a reload
This will create the reload task the way we want it and return the id for the task, whish we can use to start it. That’s just another call to the Repository like this:
And that’s it. A little more code than the second method, but much more control over what we get.
The property panel is a key part of your Qlik Sense extension. The aibility to set extension properties is what makes your extension both reusable and flexible. At the same time your options are much more limited than in the rendering part of the extension. And since this is Qlik Sense specific all of it, there is not so much information and examples available on the internet. So here are some patterns and techniques I find useful in extension development.
1. Use expressions always
Strings in the property panel can allow Qlik Sense expression by setting “expression: ‘optional’ “. Use that – always. This allows the app developer to use expressions for the property and thereby make the property dynamic. It also allows the app developer to reference a variable and use a variable extension to allow the end user to switch values for the property (horizontal/vertical for example).
It allows the app developer to use an expression, but doesn’t force her. Still a fixed string can be used, and probably will be used. And the good thing thing is you don’t have to bother about that in your extension code, you get this flexibility for free.
2. Dropdown with custom alternative
Sometimes you have just a few possible values for a property, or you want to help the app developer with a list of common values for a property. The dropdown component is a good choice for that. But you risk loosing the flexibility of the expression: the dropdown will only make it possible to select a value at design time, no possibility to make it dynamic or affected by a variable. Or the list is really not a complete list, there are alternatives for the more advanced app developer.
In those scenarios you can combine a dropdown with a separate field that allows expressions like this:
create a dropdown with your alternatives
add a ‘custom’ alternative to the dropdown
add a field with expression: ‘optional’ for the custom value
give the field a show function, that returns true if the selected value is ‘custom’
In your extension code you will need to check for custom values, something like this:
var width = layout.width === ‘custom’ ? layout.customwidth : layout.width;
3. Add properties to dimensions and measures
Sometimes you need a property for every dimension or measure. In that case you can extend the built-in dimensions and measures objects by adding new properties. You do this simply by setting the items property to the properties you want to add, and Qlik Sense will merge the default properties with the ones you hav defined. An example:
Note that the ref should begin with ‘qDef.’. That will mean it will be part of the measures property. To the app developer your roperty will look just like the built-in ones. You can do the same thing with dimensions.
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.
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:
Do not use API call
Instead add to initialProperties
List of fields
List of measures
List of dimensions
List of variables
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.
One of the great new features in Qlik Sense is snapshots and storytelling. It allows you to create a snapshot of your visualizations, with the current selection state, and then include the snapshot in a story. Behind the scenes Qlik Sense also uses snapshot for export to PDF, PowerPoint and image. This makes it even more important for you to make your extension work well with snapshots. Sometimes this is however not easy…
To turn snapshots on, you need to include a few lines in your extension:
This will give you a context menu in the client with alternatives to create snapshot and export the visualization. That might be enough, but it might not be enough. To verify it you should:
create a snapshot of your extension, include it in a story and verify that it works
export your extension to PDF and/or PowerPoint (possibly also image)
and export the story to Powerpoint/PDF
You visualization is actually used in three contexts, that are somewhat different:
the normal analyse mode, with live data, affected by changes in selection state
the snapshot/story mode with a snapshot of data and the selection state as it was when the snapshot was created
the export mode, which is also based on a snapshot, but run in a separate service on the server
To make it actually work in all, you might need to do some more work.
Make Qlik Sense wait for your extension
One problem, mainly in export, is to let Qlik Sense know when your extension actually is ready with the rendering. You might get just an empty area in your powerpoint, or just the header but no content. This might be because the image is taken before your extension is ready.
This is described where briefly in Qlik Sense help under ‘Set up “finished rendering” notification, like this:
This will return a Promise, that immediately resolves. This might not be good enough, since you might want to wait for something until you resolve. In my case, I used highcarts and highcharts has a callback function that will be called when rendering is ready. The final solution is like this:
So, I create a deferred object before calling the Highcharts rendering method. I can then return the promise that belongs to the deferred, but I do not resolve it until Highcharts tells me that rendering is complete, actually I had to add an additional delay of 1 second to make sure. There is currently no documentation of qlik.Promise in Qlik Sense help, but you can look in the angularjs documentation.
Turn animations off
If it’s still not working, you should take a look at animations. Animations in analyse mode are good (if used the right way…) and might help the user discover insights in their data, but in export they should be turned off.
In Highcharts there are actually two flags you should turn off to diable animations. It might be enough to turn off just one of them, but why not both:
The isSnapshot flag which I use to determine if we are in analyse mode or in snapshot (story or export) is undocumented, so this solution might break in future Qlik Sense versions, but in September 2017 it works.
Sometimes in your extension you need to acces the QIX Engine API. You might need to make or clear selections, apply a bookmark or something else. Traditionally you would use the Capabilities APIs for this. You would load the qlik module, get hold of the app with the help of the currApp() method, and call whatever function you needed.
Important features of enigmajs:
it includes the complete QIX API for the actual version of QIX, while the capabilities API just includes a subset
it only includes the QIX Engine API, while the capabilities APIs wraps some client-side functionality too
methods calls return a Promise, that resolves when there is a response available
it handles the invalidation of objects as the selection state changes so it works well from inside an extension
Unlike the Capabilities APIs, enigmajs does not come with a lot of dependencies on requirejs, angularjs and Qlik Sense client code. This makes it well suited for use in envorinments where you use other frameworks, like react or future frameworks we have not heard of yet. Of course if you’re using it inside an extension, you already have all of these dependencies, so that is not so important.
Note that Qlik flags enigmajs as experimental in the current release. I would be very surprised if it goes away any time soon, but details in the implementation might change, you need to be aware of that.
Finding enigmajs in an extension
It will expose all the methods defined in the Generic Object QIX engine API. As you can see, there are a lot of methods. It also has an app property, that exposes QIX Engine API app object. And the app has a global property, that is a wrapper around QIX Engine Global. This gives you access to the complete QIX Engine API.
I have converted my Variable extension for Qlik Sense to use enigmajs instead of the Capabilities API, as versions before 4.0 did. The key call of the extension is after the conversion like this:
The parameter ext is a reference to the extension itself. Since methods return a Promise, I can use the then method to run an additional command after the first command resolves. The getVariableByName reurn an enigmajs wrapper aroud a QIX Engine Variable
If you need access to QIX Engine API from within your extension, enigmajs can help you with that. Unlike the Capabilities API it provides wrappers for all methods. But you should be aware that it only wraps engine api, not client-side functionality. It however works nicely within the client and invalidation and refresh of objects will work as expected.