Calculated fields are often created in the script and stored under new aliases. But you can also create them in the user interface. What are the pros and cons with the two methods? And how are the user interface fields calculated?
I cannot count the times that I had a custom webpage with visualizations from the Qlik Sense engine open, to find out that my charts where not responding due to the websocket connection being lost.
SPOILER ALERT: I know is hard to believe, but this is NOT a blog post about the VIRUS (I won't even mention it). I figured we all needed to detox a little bit with some fun.We all know that a raw string or table with numbers isn't it the easiest thing to digest, that's why companies like Qlik exists in the first place, and that's why people need charts to help individuals to understand the numbers better.The same principle is also true about words, the old "apicture is worth a thousand words" reflects that fact. Emojis are a special set of images that can surelyhelp you to say more with less. The use of pictographs can help to reduce the time a user needs to understand a chart and for sure they canincrease the user experience among all demographics.Use case for emojisEmojis are particularly useful to be used as icons, to represent concepts that otherwise would require a number of words.Last September we launched a new app to celebrate the 2019 Rugby WorldCup in Japan. We used some emojis to improve the experience of two charts.Teams Ranking distribution chart includes medal emojis as replacement for labels for the reference lines. Each line helps to identify team's final position in the tournament history.The Tournament Medals table includes only the top 3 teams for each tournament year and the medal pictogram helps to visually understand the final position within each tournament.Check it live here:https://webapps.qlik.com/rugby-world-championship/index.html#/historicalWhere can emojis be used in Qlik Sense?Everywhere, they are just as any other character, so you can use it on labels but also as part of the load script, expressions and virtually anywhere where you can use text.Load script implementation example:Table:LOADTeamFinalPlacement,if(TeamFinalPlacement=1,'🥇', if(TeamFinalPlacement=2, '🥈', if(TeamFinalPlacement=3,'🥉',''))) as Medal,TournamentFrom somewhere;What are the emoji limitations?Limitations depends in the device used to explore the Qlik Sense app. Windows supports emoji with some limitations starting with Windows 7, check the complete list here: http://caniemoji.com/Also please be aware that the emoji you are using might not look like exactly as you see it for all the users depending on the device used to explore the Qlik Sense app. Full emoji list here: https://www.unicode.org/emoji/charts/full-emoji-list.htmlI hope you enjoy it, and please share with us how (if) are you using emojis in your apps.Arturo (@arturoqv)Related topics:https://community.qlik.com/t5/Qlik-Design-Blog/Replacing-images-with-Geometric-Shapes-as-visual-cues/ba-p/1475169
...View More
In my continuing effort to highlight our valuable Qlik Community members, our partner network and their awesome solutions - I have the pleasure of introducing you to a brand new capability available within the Write! extension by Inform.Section Access Management with Write!Managing Section Access (Dynamic Data Reduction) in Qlik requires some manual effort via Qlik scripting within a Qlik Sense app. The overall concept can involve the use of inline tables to maintain the security, user data or externally defined security tables which can be accessed by various data connectors. Once implemented, section access requires that you reload the app as necessary.Inform's extension, Write! (https://en.write.bi), now has an application directly in Qlik Sense that allows you to define, simulate and deploy your section access rules visually, with just a few clicks. You can create new Section Access rules, manage existing rules, deactivate invalid ones, automatically deploy them to an app - increasing speed and efficiency when managing Section Access on Qlik Sense apps.Watch this brief video created by Thomas Gorr, Product Manager of Write! at Inform to learn more and see it in action:For more information on this new capability please reach out to the Inform teaminfo@write.bi.Thank you Thomas for your contribution.Do you have a valuable Qlik product contribution or solution?Contact meand I will share it on the Qlik Design Blog.RegardsMike Tarallo -followSenior Product Marketing ManagerQlik
...View More
picasso.js is an awesome open source charting library from Qlik for building beautiful data visualizations quickly and easily. It’s super flexible, easy to use with hypercube data, renders in svg or canvas, and includes a lot of other great features already. But one thing it doesn’t have built in (yet) which I need when building visualizations is transitions so I developed a method for adding transitions to any picasso.js visualization (which is built into the upcoming new version of qdt-components). Let me take you through it.Check out an example at https://webapps.qlik.com/picasso-transitions/index.htmlStep 1: Create hypercube and chartThe first step is to create a hypercube, get the layout, and create a picasso.js chart./* Create a hypercube */
const object = await doc.createSessionObject({
qInfo: { qType: 'data' },
qHyperCubeDef: {
qDimensions: [{
qDef: { qFieldDefs: ['[Product Group Desc]'] },
qOtherTotalSpec: {
qOtherMode: "OTHER_COUNTED",
qOtherCounted: { qv: "10" },
qSuppressOther: true,
},
}],
qMeasures: [{
qDef: { qDef: 'Sum([Sales Amount])' },
}],
qInitialDataFetch: [{
qWidth: 2,
qHeight: 10,
}],
},
});
/* Get hypercube layout */
let layout = await object.getLayout();
/* Create chart */
const chart = picasso({
renderer: {
prio: ['canvas'],
},
}).chart({
element: document.querySelector('#chart'),
data: [
{
type: 'q',
key: 'qHyperCube',
data: layout.qHyperCube,
},
],
settings: {
scales: {
y: {
data: { field: 'qMeasureInfo/0' },
include: [0],
invert: true,
},
x: { data: { extract: { field: 'qDimensionInfo/0' } } },
},
components: [
{
type: 'axis',
dock: 'left',
scale: 'y',
},
{
type: 'axis',
dock: 'bottom',
scale: 'x',
},
{
type: 'box',
key: 'bars',
data: {
extract: {
field: 'qDimensionInfo/0',
props: {
start: 0,
end: { field: 'qMeasureInfo/0' },
},
},
},
settings: {
minor: { scale: 'y' },
major: { scale: 'x' },
box: {
fill: 'steelblue',
},
},
},
],
},
});Step 2: Animate changes to layoutNow that there's a hypercube and a chart, the next step is to animate the chart when the hypercube changes. To do this, subscribe to changes in the hypercube, and in the callback get the new layout, setup a timer, and interpolate between the previous layout and the new layout and pass the tween hypercubes to the chart's update function. It looks like this.object.on('changed', async () => { // subscribe to changes on the object
const nextLayout = await object.getLayout(); // get the next layout
const duration = 1500;
const ease = easeCubic; // easeCubic is d3-ease easeCubic function
const transitionTimer = timer((elapsed) => { // create a timer using d3-timer
// compute how far through the animation we are (0 to 1)
const t = Math.min(1, ease(elapsed / duration));
// calculate the tween layout at time t
const tweenLayout = interpolate(layout, nextLayout)(t); // interpolate function is from d3-interpolate
// update chart
chart.update({
data: [{
type: 'q',
key: 'qHyperCube',
data: tweenLayout.qHyperCube,
}],
});
// if this animation is over
if (t === 1) {
// stop this timer since we are done animating.
transitionTimer.stop();
layout = nextLayout;
}
});
});Step 3: Animate size changesNow the picasso.js chart will animate when the layout of the object changes, but it should also animate in response to CSS animations on it's parent container. A ResizeObserver can be used for that. ResizeObservers are relatively new, and should be polyfilled using the resize-observer-polyfill library. It's as simple as this.const ro = new ResizeObserver(() => {
chart.update();
});
ro.observe(document.querySelector('#chart'));Don't forget to check out the example athttps://webapps.qlik.com/picasso-transitions/index.html. The code for this example is attached.This is a rudimentary example of this approach, and does not handle things such as canceling transitions if another transition is started before the previous transition is finished. If you go through this example and want to check out my work to date on this, check out the QdtPicasso component on the working branch for the next version of qdt-components athttps://github.com/qlik-demo-team/qdt-components/blob/3.0/src/components/QdtPicasso/QdtPicasso.jsx.
...View More
Hi guys - I hope this message finds you all well and you are taking the necessary precautions to protect yourselves and others from the Coronoavirus (COVID-19). During this time of uncertainty you might ask, what can I do as a Qlik Community member to possibly help? In short - information is power and can be valuable in the fight and prevention of COVID-19. Therefore, I'd like to share some resources and offers our Qlik partners are making available that might be useful to you.#1 - The COVID-19 Community GroupThis group was formed to bring together people and resources in response to the pandemic of Coronavirus, aka COVID-19, aka SARS-CoV-2. All are welcome to share insights and sources of factual data. Currently there are a number of articles linking to various bits of information created by Qlik's own@Dalton_Ruer@JulieKae and VizLib's@joe_warbington- as well as many responses / solutions from our Qlik Community members and partners.#2 - INFORM DataLab - Free Qlik sense Write! extension licensesTo support the real heroes during the COVID-19 crisis, INFORM DataLab is giving FREE licenses of their Write! extension for Qlik Sense customers inhospitals and the healthcare industry! Write! allows you to edit data directly in Qlik with ease. Visithttps://en.write.bi/for more information. You can also contact Boris Michel at Inform directly.#3 - Inphinity 6 months free product offer to healthcare and non-profit organizationsA note from Inphinity:As COVID-19 spreads all around the globe and affects our personal lives, businesses, colleagues, families, and friends, we would like to express our SINCERE GRATITUDE to all of you who are helping us through your services in the following way:✨For any healthcare and non-profit organization, we will deliver any product from our portfolio for free for 6 months.✨You can utilize our advanced Qlik write-back solution– Inphinity #Forms (already used in healthcare in NHS, Rob O'Neill) or load your unstructured data to the #Qlik environment through our #Mole Unstructured Data Connector.You can download the products here and we will issue you the license:Inphinity Forms: https://lnkd.in/dHJ5g6nMole UDC: https://lnkd.in/eurn5HQWe can assist you to ensure patient safety and the best possible treatment in combination with Qlik and our solutions.We want to tackle this worldwide challenge with you and help you to handle this situation.If you would like to share a product, solution or service in response to this outbreak, please post in the comments below.Thank you and stay well
...View More
Congratulations to Ajay Kakar and Maria Sandorova on winning the #QlikHighlights2019 Giveaway.Thank you for sharing what made Qlik memorable during 2019 - thanks to everyone for participating.Previous post:https://community.qlik.com/t5/Qlik-Design-Blog/The-QlikHighlights-100-Gift-Card-Giveaway-Starts-Today/ba-p/1663495
...View More
IntroductionWe've covered on this blog about how to get started with the Qlik APIs and some of the associated tools like Enigma.js.But what if you're completely new to Qlik Sense and feel more comfortable developing websites and building visualizations? You're probably thinking: "Do I really have to learn something else? Just get me started!" Well this is what we'll try to do here - give web developers familiar with modern web development (e.g. React, Webpack, ES6+) an approachable tutorial to connect to Qlik Sense, understand the layout of the app, and get some data within 20 minutes!Before we get started, we will assume that you have some knowledge of web development as well as access to a Qlik Sense server and a pre-existing app. To follow along, take a look at this repo on GitHub and download the Consumer Goods Sales app from our Demo Site.Project SetupOur first step will be to clone the example repo for the basic setup of the project. In this tutorial, we have already installed the development dependencies (Webpack, Webpack Dev Server, Babel) as well as the dependencies for the app (React, ReactDOM, Enigma.js). You are probably familiar with React and ReactDOM but probably not Enigma.js which is what we'll use to connect to and interact with the Qlik Engine JSON API. Enigma.js allows us to easily use all the methods that we need in simple JavaScript.To get started, simply clone the repo, install the dependencies, and then we'll get going.git clone https://github.com/qlik-demo-team/qlik-engine-tutorial my-qlik-app
cd my-qlik-app
npm install
npm run devGo to http://localhost:8080 to see "My Amazing Qlik Sense Mashup!" on your screen. Note: to see the final result of any one section, you can switch to one of five branches in the repo: start (setup), connection (connecting to Qlik Sense), hypercube (getting data), list-object (making a selection), finished (completed project).Connecting to Qlik SenseOne of the first steps in building a web app with access to Qlik Sense is to get the domain for your Qlik Sense server as well as your app ID. Going to your Qlik Sense Hub is an easy way to get the domain. You can ignore the "https://" and just get the url of the Qlik Server (e.g. qlik-server.example.com) or if just running locally (localhost).Next you'll need the app ID of the app that you wantto access from your website. A simple way to do that is to just open the app and then look at theURL - the app ID is right in that url after "/sense/app/[appID]/" (your URL will probably not have the "windows" before "sense").Now that we have the domain and app ID, we can connect to Qlik Sense. We'll show the code first and then explain what we're doing. Copy and paste the code below into the Home.js file and update it with the domain of your Qlik server and app ID.const enigma = require('enigma.js');
const schema = require('enigma.js/schemas/12.170.2.json');
const SenseUtilities = require('enigma.js/sense-utilities');
const config = {
host: '', // <== Qlik server domain here
secure: true,
port: 443,
prefix: '',
appId: '', // <== app ID here
};
const url = SenseUtilities.buildUrl(config);
const qDocPromise = enigma.create({ schema, url }).open().then(global => global.openDoc(config.appId));
console.log(qDocPromise)Enigma.js is a Promise-based library so as you'll notice, in your console, it says Promise {<pending>} meaning it has just logged the Promise itself, not the object. Establishing the connection is a great first step in understanding how Enigma works and how we'll be communicating with our Qlik server.Because everything is Promise-based, to actually see the returned value, we'll need an extra bit of code:qDocPromise.then((doc) => {
console.log(doc);
})The resulting object is what we'll use to do most of the talking to the Qlik Sense server. Without going into much further detail, this object is called the "Doc" (in older versions, it was called the App but is now usually just called the Doc).Listing the Available FieldsNow that we have made our connection to the Qlik server and opened the correct app, let's get a better understanding of the data by listing out the fields:qDocPromise.then((doc) => {
console.log(doc);
doc.createSessionObject({ qInfo: { qType: 'fields' }, qFieldListDef: {}}).then((fields) => fields.getLayout().then((layout) => {
const { qItems } = layout.qFieldList;
const sorted = qItems.sort((a,b) => a.qName > b.qName ? 1 : -1)
console.log(sorted)
}))
})If you open your console, you can see that the resulting array has of over 200 fields. Building a mashup without understanding anything about the data is difficult but the above snippet does a good job of just listing all the fieldsavailable to you. But because this is an introductory exercise, we're going to pick a couple fields that we know beforehand and see if we can get some data!Source: List fields in an appGetting DataGetting started with the Qlik APIs is difficult if you are not familiar with the jargon. In the Qlik Engine JSON API documentation, you'll see terms like "hypercube", "dimension", and "measure" thrown around a good bit. A hypercube is just the code that requests the data you want. Some Qlik apps can be quite large with hundreds of fields and we obviously won't use ALL of that data in every visualization. A hypercube allows us to pick only what we want. A hypercube is comprised of dimensions (typically a category in your data, e.g. "customer", "product", etc.) and measures (typically some value on which you can make calculations, e.g. sum, count, average, etc.). Copy the code below into a new file called hypercube.js:// hypercube.js
const hypercube = {
qInfo: { qId: 'Consumer Sales', qType: 'data' },
qHyperCubeDef: {
qDimensions: [
{ qDef: { qFieldDefs: ['[Product Group Desc]']}, qFieldLabels: ['Product Group'] }
],
qMeasures: [
{ qDef: { qDef: '=SUM([Sales Margin Amount])/SUM([Sales Amount])', qLabel: 'Margin' }},
],
qInitialDataFetch: [{
qTop: 0, qLeft: 0, qWidth: 10, qHeight: 1000,
}],
qInterColumnSortOrder: [],
qSuppressZero: true,
qSuppressMissing: true,
}
}
export default hypercube;Now that we have our hypercube, let's use our doc object to get the data. First import the hypercube at the top of the file, just below your Enigma imports, and then add the following code:// Enigma.js imports
import hypercube from './hypercube';
// CODE
qDocPromise.then((doc) => {
// new code
doc.createSessionObject(hypercube).then((obj) => obj.getLayout().then(layout => {
console.log(layout);
const dataPages = layout.qHyperCube.qDataPages[0].qMatrix
console.log(dataPages)
}))
})Boom! And just like that, we now have some data! In your console, you'll be able to see both the layout object as well as the data. For some users, this is good enough - if you know the fields you want, you can make as many hypercubes as you'd like to get the data you're looking for. From here, you can use vanilla JavaScript to clean-upthe array to feed into a visualization library like D3 or use Picasso.js which has a plugin that can work with hypercubes.Making a SelectionBy this point, we have made our connection to Qlik Sense, we've written our first hypercube, and we've actually gotten some data. But how do we make selections? One of Qlik's key selling points is being able to interact with the data and make selections. To do that, we'll use another important object in the Qlik Engine called a List Object. List Objects, unlike hypercubes, only have one dimension and no measures. They aren't designed to give you data but rather give you information on a particular dimension. Let's dig into the example. First, create a new file called listObject.js:// listObject.js
const listObject = {
title: "A list object",
description: "Description of the list object",
qInfo: { qId: 'Consumer Sales List Object', qType: 'List Object'},
qListObjectDef: {
qStateName: "$",
qDef: { qFieldDefs: ['[Product Group Desc]'], qFieldLabels: ["Product Description"], qSortCriterias: [{qSortByLoadOrder: 1}]},
qInitialDataFetch: [{
qTop: 0, qLeft: 0, qWidth: 10, qHeight: 1000,
}],
},
}
export default listObject;Import your list object at the top of the page. Then, inside the qDocPromise, right below the code to fetch the hypercube data, copy and paste the following:// top of page, below other import statements
import listObject from './listObject';
// CODE
qDocPromise.then((doc) => {
// Getting data from hypercube
doc.createSessionObject(hypercube).then((obj) => obj.getLayout().then(layout => {
console.log(layout);
const dataPages = layout.qHyperCube.qDataPages[0].qMatrix
console.log(dataPages)
}))
// NEW CODE: List Object
doc.createSessionObject(listObject).then((obj) => {
obj.getListObjectData('/qListObjectDef',[ {qLeft: 0, qTop: 0, qWidth: 10, qHeight: 100}]).then(objectData => {
console.log(objectData);
})
})
})If we open our console and peak inside objectData, we see that inside the qMatrix property, there is an array with 17 items. Each item is an array with a single object that represents a possible value for the field of "Product Group Desc". There is a descriptor/title/name for that field (qText), a numeric value (qNum), an element number (qElemNumber), and it's selection state (qState). Let's try making a selection. Just for fun, let's pick "Beverages", which as we can see in the picture below has a qElemNumber of 2.Now, update the code like this:qDocPromise.then((doc) => {
// Getting data from hypercube
doc.createSessionObject(hypercube).then((obj) => obj.getLayout().then(layout => {
console.log(layout);
const dataPages = layout.qHyperCube.qDataPages[0].qMatrix
console.log(dataPages)
}))
// UPDATED CODE: List Object
doc.createSessionObject(listObject).then((obj) => {
obj.getListObjectData('/qListObjectDef',[ {qLeft: 0, qTop: 0, qWidth: 10, qHeight: 100}]).then(objectData => {
console.log(objectData);
obj.selectListObjectValues('/qListObjectDef', [2], true, false).then((res) => {
console.log(res);
obj.getListObjectData('/qListObjectDef',[ {qLeft: 0, qTop: 0, qWidth: 10, qHeight: 100}]).then(objectData2 => {
console.log(objectData2)
})
})
})
})
})Here is a quick rundown of what's happening. The doc.createSessionObject() creates our list object. We then use the resulting list object (which I've called `obj`) to call obj.getListObjectData(). When we logged that to the console, we saw that there was an array of 17 items, all of them with the name of the field and a qState of "O". We then called obj.selectListObjectValues() and selected "Beverages" which had a qElemNumber of 2 (we need to use qElemNumbers to tell the Qlik Engine which item to select). The log of "true" tells us that it was successful. We then call obj.getListObjectData() again to see that the list has been updated. There are still 17 items in the array but now we see that everything except "Beverages" has a qState of "X" while Beverages has a qState of "S". Selecting a value in this way is akin to clicking on a particular bar in a Qlik bar chart - you are selecting "Beverages" and now all the charts in Qlik Sense will, if they are connected to the column "Product Group Desc", show only the data for "Beverages". Here is the console output just to confirm our selections:ConclusionSo there it is, you've done it! You've learned the three most fundamental tasks in creating a Qlik Sense mashup:Connecting to Qlik SenseCreating a Hypercube and Getting DataCreating a List Object and Making a SelectionWith those three skills, you'll be able to make an interactive web app with your Qlik Data. In this tutorial, we scraped the surface of all that you can do with the Qlik Engine JSON API but we hope that you can now feel free to explore a bit. Here are a few resources that we think will help you get up-to-speed with the Qlik APIs:Qlik Sense for Developers HelpQlik Engine JSON API ReferenceBlog Post: Getting Started with Qlik APIs
...View More
Dimension limitations offer a quick and easy way to measure performance of your metrics by assigning user defined limitations, that respect fixed, exact, relative and calculated values. As a result, your visualization will display a reduced set of values according to the definition of the limitation.Regards,Mike TaralloQlik
...View More
The Qlik Community currently has 97,142 register members from around the world. In which over 2,000 could be online almost at any time! We are seeking answers to questions, helping others find solutions, informing the Qlik team of product issues, or simply browsing the extensive library in search of valuable content. Qlik Community members have varying skills that range from newbies to “Jedi Masters” 😀 . BUT – our members are not just limited to posting questions and providing answers to one another, they also post solutions and helpful tutorials about various Qlik products, deployment scenarios and situations.Which brings me to introducing@rohitk1609 (Rohit Kumar). Rohit has reached out to me in an effort to highlight and share some of the fantastic information he has created when working with the Qlik Analytics Platform.Rohit is a Sr. Business Intelligence Administrator in New Delhi, India and is ranked as a Contributor III in the Qlik Community. His 8+ years of experience with Qlik products, consulting and implementing BI solutions has prompted him to create and share what he has learned when deploying many instances of Qlik Sense. Currently, his primary role is to deploy and manage Qlik multi-node sites - which are robust, scalable and highly reliable. Rohit did not find a particular document that explained everything he needed to know when it came to deploying a Mulit-node Qlik Sense site and thus made an effort to publish the steps he followed, including consolidating many of the Qlik Help materials to help guide you towards a successful multi-node deployment. He also has answered many questions posted to his document thread and will be happy to answer any of yours.• Best Practices of Qlik Sense Multi-Node Setup, Load Balancing & MaintenanceI'd like to thank Rohit for his contribution and I encourage all of you to share what you have learned when working with Qlik so others may also benefit from it.The Qlik Community – works together to achieve successful outcomes through conversation and collaboration.Do you have a valuable Qlik product contribution or solution? Contact me and I will share it on the Qlik Design Blog.RegardsMike Tarallo - followSenior Product Marketing ManagerQlik
...View More