Qlik Community

Qlik Design Blog

All about product and Qlik solutions: scripting, data modeling, visual design, extensions, best practices, etc.

Employee
Employee

Starter project for developing QAP-powered apps with React and enigma.js

I've been doing most of my projects lately with React and enigma.js, and developing some general patterns along the way that I've been working into a starter project that I can use as a starting point. I'd like to share that with you today, and potentially start a discussion around the design decisions I've made thus far.

The starter project can be found at GitHub - fkabinoff/qlik-react-starter: Starter project for rapidly developing QAP-powered apps. It's still very much in development, but there's a decent framework and dev environment in place, as well as a few useful components.

Overview

The project uses enigma.js to interface with the Qlik engine, along with React, webpack, Babel, ESLint, Sass, and a few other goodies. Really, a pretty standard React app with enigma.js added. The qDoc, which is the name the enigma.js docs use for the connection to the Qlik app is created in a plain Javascript module and simply imported to any file that needs to use it.

I use react-hot-loader, which allows you to change react components without refreshing the page or losing state, and I really like it. It has it's problems, most noticeably to me that it doesn't play very nicely with higher order components, but the ability to change my React components and not have to reload the page or lose state helps me develop faster.

I'm using the latest Babel preset, which enables es2015, es2016, and es2017, and Babel plugins which enable decorators, spread syntax, and class properties. I can't believe we actually wrote Javascript before this stuff.

I use the very popular airbnb config for ESLint. It helps keep the code healthy and uniform.

I make use of reactstrap, a library of Bootstrap 4 components for React, and SASS for customizing and mixing in Bootstrap styles, as well as creating a few utility classes. I prefer using reactstrap over some of the more feature-rich React UI libraries, because I often find it creates more work trying to make the components of those UI libraries, such as Material UI, play nicely with how I want a component in a Qlik-powered app to function since in a Qlik-powered app the Qlik engine acts as a state machine, and many of the UI libraries with more features expect the state to be managed and changed by the client. Reactstrap gives me what I need, without being too opinionated about it.

I use the "render prop" pattern in place of higher order components. The render prop pattern is simply passing a component as a prop to another component for that component to render it. It basically works like a higher order component does, but to me it's a bit simpler, a little more flexible, and doesn't mess with react-hot-reload or PropTypes checking.

Notably, I don't use a state manager like Redux or MobX, and this may be my most contentious decision. To me, the use of a state manager in most instances is redundant when building a Qlik-powered app. Qlik already manages my state, and shares it between components. I hardly, if ever, have state that needs to be managed outside of Qlik in my Qlik-powered apps, and using a state manager forces me to do extra work to keep the client state and Qlik state in sync. I don't like it.

It would be very interesting to hear what you think about these design decisions, and the decisions that you've made with your own Qlik projects.

Components

Now, let's take a look at the actual components. There are currently 4 Qlik-specific components, but I expect to add more as I continue developing this. I tried to design the Qlik-specific components to expect props which are identical to values defined in Qlik docs, and pass down values directly returned by the Qlik engine, in order to standardize as much as possible. Though in some instances, I broke that rule. For instance, since the QlikObject wrapper, which I'll talk about in a moment, is really only designed to work with an object that fetches one page, it didnt make sense to pass down the qDataPages returned by the Qlik generic object getData method. Instead, I simply pass down the object at the first index of qDataPages.

QlikObject.jsx

The QlikObject component implements the render prop pattern, and contains the logic to create and manage a Qlik generic object and its state. It passes down the Qlik generic object information to the component defined in the Component prop, which is responsible for rendering something.


QlikVirtualScroll.jsx

The QlikVirtualScroll component implements the render prop pattern, and paginates data on vertical scroll so only data in view gets rendered. It passes down a subet of the qMatrix to the component defined in the Component prop, which is responsible for rendering something. It is used by the QlikFilter and QlikTable components.


QlikFilter.jsx

The QlikFilter component renders a dropdown that acts as a Qlik Sense filter. It's meant to be used as the `Component` prop of a `QlikObject` component a type of `qListObject`. This component doesn't need to be passed any props other than the props passed to it by `QlikObject`.


QlikTable.jsx

The QlikTable component renders a table. It's meant to be used as the `Component` prop of a `QlikObject` component with a type of `qHyperCube`. This component requires a prop `columnWidths` to be passed to it, defining the widths of the columns of the table. This prop should be passed using the `componentProps` prop of the `QlikObject`.



Finishing up

Go to GitHub - fkabinoff/qlik-react-starter: Starter project for rapidly developing QAP-powered apps‌, download the zip, run npm install, and npm run dev, and you can check out the QlikFilter and QlikTable components in action, and check out the code. I'll be adding more components and styles as I'm still pretty actively developing it, so watch the repo if you're interested, and let me know what you think.

9 Comments
Luminary
Luminary

I like it.You almost make me want to try this.

But for those not iniated with React or Webpack on Windows. Can you write a tutorial on how you use these tools with Qlik?

Kind Regards,

Dion

0 Likes
988 Views
Employee
Employee

To get up and going, the only prerequisite is you have node.js installed (Node.js). Then just go to the project's page at qlik-react-starter‌ and download the zip. Unzip the zip file, then open a command prompt and cd to the folder location. In the command prompt type `npm install`, which will install everything you need, and wait for that to finish. Then type `npm run dev` and it'll do its thing and open a browser window with an example running.

From there, you can open the folder in a text editor (I highly recommend Visual Studio Code‌ nowadays) and start playing around with the code. You can check out the webpack config to get a feel for what's going on, but you most likely don't have to customize that. The real action is in the src/components folder, you can jump there and start checking out and editing the code for the components.

0 Likes
988 Views
elias_chafloque
New Contributor II

Thanks Francis, this is great!!!

I managed to the the build of your React application

Just one remark: My first build failed, I had to run "npm install node-sass" and then "npm run dev" worked perfectly.

Thanks!qlik-react.PNG

988 Views
elias_chafloque
New Contributor II

Hi fka

For us, it is very important to use the Capabilities at least for our charts, as we would not wish to re-create them.

So I took your React project, and tried to bring also the Capabilities API --> In other posts you are showing how to include it.

We managed to do it , but our problem is how to make the react components talk with the charts (when doing selections). Probably I am doing something wrong, in a personal project I am using same session and enigma always pulls full data even if i have selections.

And my question is... is it bad idea to use enigma and also the capabilities combo (require.js, qlik.js) together?

Thanks

-Elias

react-qlik-capabilities.PNG

0 Likes
988 Views
Employee
Employee

Worked this out with Elias earlier. For anyone else who experiences the same thing, the websocket routes must be the same to share session. So, you just have to open up the qDoc.js file, and change the url param in the enigma.create method to match the url of the websocket of the session you are trying to have shared.

988 Views
alan_grn
Contributor

Great starter kit. Is it possible to show how to use this with authentication against a Qlik Sense Enterprise server using certificates.

0 Likes
988 Views
Employee
Employee

you would need to create a custom authentication module

0 Likes
988 Views
alan_grn
Contributor

Are there any examples which show how to do this with express and node. All examples show how to do this on local host. I am trying to get this working using certificates to authenticate.

0 Likes
988 Views
alan_grn
Contributor

This is great.

How would we use this to use an expression? 

I have tried the following in qProps.js with

qProps.testExpression = {

  qInfo: {

    qType: 'StringExpression',

  },

  expr: {

    qStringExpression: { qExpr: "='count(ID) = ' & count(ID)" },

  },

};

and the following in QlikObjects.jsx but it does not appear to work. How do I set this up?

  expression: {

    path: 'null',

    dataFunc: 'null',

  },

988 Views