Skip to content

Creating a session app - Advanced tutorial

Note: Where possible, use qlik-embed and qlik/api rather than this framework.

Learn how to create a session app, including a couple of visualizations on the fly using the Capability APIs.

If you are new to session apps, review apps and session apps before continuing.

The session app is created when clicking a button which also loads data from the prepared test script and displays two visualizations.

The Session App Tutorial screen. Two
visualizations are displayed, a bar chart and a pie chart.

The Session App Tutorial screen. Two visualizations are displayed, a bar chart and a pie chart.

Creating the container

Create a folder that will contain your assets. The folder can be created in a location of your choice.

Creating the main script file

Then it is time to create the main JavaScript file. This file is placed in the same folder that you just created. Name the file session-app-tutorial.js.

Configuring your connection to Qlik Cloud

The Qlik Cloud tenant being used must be configured in your mashup. This is needed for the following reasons:

  • To define the actual Qlik associative engine connection, which is used when you open an app or get a list of apps. This is covered by the config JavaScript object, used as a parameter in the qlik.sessionApp() call.

  • To define where the Qlik Sense client side software and extensions should be loaded from. This is achieved by configuring reguirejs with the require.config() call and setting the baseUrl.

In most cases, you use the same Qlik CLoud tenant for both purposes, which means you can create the baseUrl from the config object.

const config = {
  host: '<TENANT_URL>', //for example, 'abc.us.qlikcloud.com'
  prefix: '/',
  port: 443,
  isSecure: true,
  webIntegrationId: '<WEB_INTEGRATION_ID>'
};
require.config( {
  baseUrl: ( config.isSecure ? "https://" : "http://" ) + config.host + 
  (config.port ? ":" + config.port : "") + config.prefix + "resources"});

Setting the global require and alert

The JavaScript file is loaded in the browser when your mashup is used. RequireJS is used as a module loader.

require( ["js/qlik"], ( qlik )=> {
  qlik.on( "error", ( error )=> {
    $( '#popupText' ).append( error.message + "<br>" );
    $( '#popup' ).fadeIn( 1000 );
  } );
  $( "#closePopup" ).click( ()=> {
    $( '#popup' ).hide();
  });

Creating the session app

The session app is created using the qlik.sessionApp method.

$( ".create-session-app" ).click( ()=> {
  const sessionApp = qlik.sessionApp(config);
} );

Setting and loading the data load script

The script used in this tutorial is a from a shortened version of the prepared test script that loads a set of inline data fields into the session app.

The script is set with the app.setScript method and then loaded into the session app using the app.doReload method.

$( ".create-session-app" ).click(()=> {
  const sessionApp = qlik.sessionApp(config);
  const script = 
  "Characters: Load Chr(RecNo()+Ord('A')-1) as Alpha, RecNo() as Num 
  autogenerate 26;   
  ASCII: Load if(RecNo()&gt;=65 and RecNo()&lt;=90,RecNo()-64) as Num,
  Chr(RecNo()) as AsciiAlpha,   RecNo() as AsciiNum autogenerate 255  Where
  (RecNo()&gt;=32 and RecNo()&lt;=126) or RecNo()&gt;=160 ;   Transactions: Load
  TransLineID,   TransID,  mod(TransID,26)+1 as Num,
  Pick(Ceil(3*Rand1),'A','B','C') as Dim1,
  Pick(Ceil(6*Rand1),'a','b','c','d','e','f') as Dim2,
  Pick(Ceil(3*Rand()),'X','Y','Z') as Dim3,  Round(1000*Rand()*Rand()*Rand1) as
  Expression1,  Round(  10*Rand()*Rand()*Rand1) as Expression2,
  Round(Rand()*Rand1,0.00001) as Expression3; Load   Rand() as Rand1,  IterNo()
  as TransLineID,  RecNo() as TransID Autogenerate 1000  While Rand()&lt;=0.5 or
  IterNo()=1;  Comment Field Dim1 With 'This is a field comment';";
  sessionApp.setScript(script).then(()=>{
    const stop = setInterval(()=>{
      sessionApp.global.getProgress(sessionApp.model.handle).then((progress)=>{
       //console.log("DoReload progress", progress);
      });
    }, 100);
    sessionApp.doReload()
  });
});

Creating the visualizations

Use the app.visualization.create method to create two visualizations: a bar chart and a pie chart. Also add a selections bar.

sessionApp.doReload().then(function(result){
  sessionApp.visualization.create('barchart',["Dim1", "=Sum([Expression1])"],
  {"title":"Session App - Bar Chart"}).then((vis)=>{
    vis.show("QV01");
  });
  sessionApp.visualization.create('piechart',["Dim1", "=Count([Expression1])"],
  {"title":"Session App - Pie Chart"}).then((vis)=>{
    vis.show("QV02");
  });
  sessionApp.getObject('CurrentSelections','CurrentSelections');
});

Setting actions for selections

Then use the app.clearAll, app.forward, app.back, and app.lockAll methods to add actions for clearing all selections, stepping back and forward in the selection history list, and locking all selections. These actions can be assigned to buttons in the HTML.

These actions can be assigned to buttons in the HTML.

sessionApp.doReload().then((result)=>{
  sessionApp.visualization.create('barchart',["Dim1", "=Sum([Expression1])"],
  {"title":"Session App - Bar Chart"}).then((vis)=>{
    vis.show("QV01");
  });
  sessionApp.visualization.create('piechart',["Dim1", "=Count([Expression1])"],
  {"title":"Session App - Pie Chart"}).then((vis)=>{
    vis.show("QV02");
  });
  sessionApp.getObject('CurrentSelections','CurrentSelections');
  $( ".clear-all" ).click( ()=>{
    sessionApp.clearAll();
  } );
  $( ".step-forward" ).click( ()=>{
    sessionApp.forward();
  } );
  $( ".step-back" ).click( ()=>{
    sessionApp.back();
  } );
  $( ".lock-all" ).click( ()=>{
    sessionApp.lockAll();
  } );
});

Creating the main HTML file

Create an HTML file and name it session-app-tutorial.html. Save the file in the same folder as the previously created files.

Defining the relationships

Relationships between the current document and the linked Qlik Cloud defined style sheets are specified in link rel tags inside the head of the HTML file.

<link rel="stylesheet" href="<TENANT_URL>/resources/autogenerated/qlik-styles.css">
<link rel="stylesheet" href="session-app-tutorial.css">
<script src="<TENANT_URL>/resources/assets/external/requirejs/require.js"></script>
<script src="session-app-tutorial.js"></script>

Placing the session objects

The session objects that have been defined in the JavaScript file are placed inside div tags inside the body of the HTML file.

<div class="sections section-3">
  Test qlik.sessionApp()
</div>
<div class="content content-3">
  <div class="row">
    <button class="lui-button  lui-button--info create-session-app">Create Session
    App</button>
    <div class="text1">*Creates a session app loaded with data from a prepared
    test script (Ctrl+00). </div>
  </div>
  <div class="row result">
    <div class="bold">RESULT</div>
  </div>
  <div id="CurrentSelections"></div>
  <div class="flex-container">
    <div id="QV01" class="object"></div>
    <div id="QV02" class="object"></div>
  </div>
  <div class="row result buttons-wrapper">
    <button class="lui-button  lui-button--info clear-all">Clear all selections</button>
    <button class="lui-button  lui-button--info step-forward">Step forward</button>
    <button class="lui-button  lui-button--info step-back">Step back</button>
    <button class="lui-button  lui-button--info lock-all">Lock all selections</button>
  </div>
  <div class="row result">
    <div class="bold">NOTE:</div>
    <div>Two visualizations should be displayed: a bar chart and a pie chart.</div>
  </div>
</div>

Styling your mashup

To add some styling to your mashup, create a CSS file and name it session-app-tutorial.css. This file is also saved in the same folder as the previously created files.

Extract

.app-title{
  position: absolute;
  font-size: 15px;
  font-weight: bold;
  top: 14px;
  left: 46px;
}

.object{
  flex: 1 1 auto;
  height: 300px;
  min-width: 400px;
  margin: 45px 0 0 45px;
}

.header-row{
  height: 70px;
  background: rgb(70, 139, 176);
  color: rgb(255, 255, 255);
  line-height: 70px;
  font-size: 33px;
  font-family: Arial;
  text-align: center;
  border-bottom: 2px solid white;
}

.sections{
  height: 35px;
  background: #468bb0;
  color: white;
  line-height: 35px;
  font-size: 18px;
  font-family: Arial;
  text-align: center;
  cursor: pointer;
  border-bottom: 2px solid white;
}

.content{
  font-family: Arial;
  display: none;
}

Tutorial source code

Explore the full source code of this tutorial below.

session-app-tutorial.js

Click to expand this section
const config = {
  host: '<TENANT_URL>', //for example, 'abc.us.qlikcloud.com'
  prefix: '/',
  port: 443,
  isSecure: true,
  webIntegrationId: '<WEB_INTEGRATION_ID>'
};
require.config( {
  baseUrl: ( config.isSecure ? "https://" : "http://" ) + config.host + 
  (config.port ? ":" + config.port : "") + config.prefix + "resources"});

require( ["js/qlik"], ( qlik ) => {
  qlik.setOnError( ( error ) => {
    $( '#popupText' ).append( error.message + "<br>" );
    $( '#popup' ).fadeIn( 1000 );
  } );
  $( "#closePopup" ).click( () => {
    $( '#popup' ).hide();
  } );

  $( ".create-viz" ).addClass( "lui-disabled" );

  $( ".section-3" ).click( () => {
    $( ".content-3" ).toggleClass( "show-section" );
  } );

  $( ".get-script" ).click( () => {
    const appId = $( ".app-id" ).val();
    app1 = qlik.openApp(appId, config);
    app1.getScript().then(( script ) => {
      $( ".get-script-result" ).val( script.qScript );
      //console.log( script );
    });
  });

  $( ".set-script" ).click(  () => {
    $( ".msg-success" ).removeClass( "show" );
    $( ".msg-fail" ).removeClass( "show" );

    const script = $( ".set-script-input" ).val();
    const app2 = qlik.sessionApp(config);
    app2.setScript(script).then(() => {
      const stop = setInterval(() => {
        app2.global.getProgress(app2.model.handle).then((progress) => {
          //console.log("DoReload progress", progress);
        });
      }, 100);
    app2.doReload().then((result) => {
      if( result ){
        $( ".msg-success" ).addClass( "show" );
      } 
      else {
        $( ".msg-fail" ).addClass( "show" );
      }
    }).finally(( => {
      clearInterval(stop);
    }).catch( ( error ) => {
      console.log( error );
    } );

    app2.getScript().then(( script ) => {
      $( ".set-script-result" ).val( script.qScript );
      });
    });
  });

  $( ".create-session-app" ).click( () => {
    const sessionApp = qlik.sessionApp(config);
    const script2 = "Characters: Load Chr(RecNo()+Ord('A')-1) as Alpha, RecNo()
    as Num autogenerate 26;   ASCII: Load   if(RecNo()>=65
    and RecNo()<=90,RecNo()-64) as Num,  Chr(RecNo()) as AsciiAlpha,   RecNo() as
    AsciiNum autogenerate 255  Where (RecNo()>=32 and RecNo()<=126) or
    RecNo()>=160 ;   Transactions: Load  TransLineID,   TransID,
    mod(TransID,26)+1 as Num,  Pick(Ceil(3*Rand1),'A','B','C') as Dim1,
    Pick(Ceil(6*Rand1),'a','b','c','d','e','f') as Dim2,
    Pick(Ceil(3*Rand()),'X','Y','Z') as Dim3,  Round(1000*Rand()*Rand()*Rand1) as
    Expression1,  Round(  10*Rand()*Rand()*Rand1) as Expression2,
    Round(Rand()*Rand1,0.00001) as Expression3; Load   Rand() as Rand1,  IterNo()
    as TransLineID,  RecNo() as TransID Autogenerate 1000  While Rand()<=0.5 or
    IterNo()=1;  Comment Field Dim1 With 'This is a field comment';";

    //createdApp.getScript().then((script)=>{
    sessionApp.setScript(script2).then(() => {
      const stop = setInterval((){
        sessionApp.global.getProgress(sessionApp.model.handle).then((progress)=>{
          //console.log("DoReload progress", progress);
        });
      }, 100);
      sessionApp.doReload().then((result) => {
        sessionApp.visualization.create('barchart',["Dim1",
        "=Sum([Expression1])"],   {"title":"Session App - Bar Chart"}).then((vis)=>{
        vis.show("QV01");
        });
        sessionApp.visualization.create('piechart',["Dim1",
        "=Count([Expression1])"],   {"title":"Session App - Pie Chart"}).then((vis)=>{
        vis.show("QV02");
        } );
        sessionApp.getObject('CurrentSelections','CurrentSelections');
        $( ".clear-all" ).click( () => {
          sessionApp.clearAll();
        } );
        $( ".step-forward" ).click( () => {
          sessionApp.forward();
        } );
        $( ".step-back" ).click( () => {
          sessionApp.back();
        } );
        $( ".lock-all" ).click( () => {
          sessionApp.lockAll();
        } );

      }).finally(function(){
        clearInterval(stop);
      }).catch( function ( error ) {
        console.log( error );
      });
    });
  });
});

session-app-tutorial.html

Click to expand this section
<!doctype html>
<html><head>
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title>Qlik Sense Mashup</title>
  <meta charset="utf-8">
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <meta name="HandheldFriendly" content="True">
  <meta name="MobileOptimized" content="320">
  <meta name="viewport" content="width=device-width, initial-scale=1.0,
   maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <meta http-equiv="cleartype" content="on">
  <link rel="stylesheet" href="<TENANT_URL>/resources/autogenerated/qlik-styles.css">
  <link rel="stylesheet" href="session-app-tutorial.css">
  <script src="<TENANT_URL>/resources/assets/external/requirejs/require.js"></script>
  <script src="session-app-tutorial.js"></script>
</head>
<body style="overflow: auto">
  <div class="header-row">
    Session app tutorial
  </div>
  <div class="sections section-3">
    Test qlik.sessionApp()
  </div>
  <div class="content content-3">
    <div class="row">
      <button class="lui-button  lui-button--info create-session-app">Create
      Session App</button>
      <div class="text1">*Creates a session app loaded with data from a prepared
        test script (Ctrl+00).</div>
    </div>
    <div class="row result">
      <div class="bold">RESULT</div>
    </div>
    <div id="CurrentSelections"></div>
    <div class="flex-container">
      <div id="QV01" class="object"></div>
      <div id="QV02" class="object"></div>
    </div>
    <div class="row result buttons-wrapper">
      <button class="lui-button  lui-button--info clear-all">Clear all selections</button>
      <button class="lui-button  lui-button--info step-forward">Step forward</button>
      <button class="lui-button  lui-button--info step-back">Step back</button>
      <button class="lui-button  lui-button--info lock-all">Lock all selections</button>
    </div>
    <div class="row result">
      <div class="bold">NOTE:</div>
      <div>Two visualizations should be displayed: a bar chart and a pie chart.</div>
    </div>
  </div>

  {/*Error Popup*/}
  <div id="popup">
    <button type="button" class="close" data-dismiss="modal" aria-label="Close"
    id="closePopup"><span aria-hidden="true"></span></button>
    <p id="popupText"></p>
  </div>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>

  </body>
</html>

session-app-tutorial.css

Click to expand this section
@keyframes example {
  0% { height: 0; }
  25% { height: 25%; }
  50% { height: 50%; }
  100% { height: 100%; }
}

.data-1, .data-2, .data-3, .data-4{
  width:150px;
  margin: 0 10px;
}

.flex-container {
  display: flex;
  flex-wrap: wrap;
  padding: 0 45px 45px 0;
  background: #e3e4e5;
  position:relative;
}

.qvplaceholder, .qvobject {
  flex: 1 1 auto;
  height: 300px;
  min-width: 400px;
  margin: 45px 0 0 45px;
}

.big-wrap{
  display: flex;
}

.break-line{
  border-right: 3px solid white;
}

.app-title{
  position: absolute;
  font-size: 15px;
  font-weight: bold;
  top: 14px;
  left: 46px;
}

.object{
  flex: 1 1 auto;
  height: 300px;
  min-width: 400px;
  margin: 45px 0 0 45px;
}

.header-row{
  height: 70px;
  background: rgb(70, 139, 176);
  color: rgb(255, 255, 255);
  line-height: 70px;
  font-size: 33px;
  font-family: Arial;
  text-align: center;
  border-bottom: 2px solid white;
}

.sections{
  height: 35px;
  background: #468bb0;
  color: white;
  line-height: 35px;
  font-size: 18px;
  font-family: Arial;
  text-align: center;
  cursor: pointer;
  border-bottom: 2px solid white;
}

.content{
  font-family: Arial;
  display: none;
}

.show-section{
  display: inline;
}

.row{
  display: flex;
  line-height:28px;
  padding: 10px 20px;
}

.app-id, .created-app, .app-id-session {
  width: 300px;
  margin: 0 30px 0 5px;
}

.object-id-1, .object-id-2 {
  width: 150px;
  margin: 0 30px 0 5px;
}

.script{
  margin: 0px 30px 0px 11px;
  min-height: 189px;
  width:600px;
}

.bold{
  font-weight:bold;
  padding-right: 6px;
}

.result{
  background: #e3e4e5;
}

.text1{
  padding-left: 15px;
}

.msg-success{
  color: green;
  display:none;
}

.msg-fail{
  color: red;
  display:none;
}

.msg-success-2{
  color: green;
  display:none;
  padding-left:15px;
}

.msg-fail-2{
  color: red;
  display:none;
  padding-left:15px;
}

.show{
  display: inline;
}

.buttons-wrapper{
  display: flex;
  justify-content: center;
}

.buttons-wrapper button{
  margin-right: 15px;
}

.app-wrapper{
  flex: 1 1 auto;
}

#popup {
  background-color: #c3534b;
  color: #FFFFFF;
  position: fixed;
  max-width: 250px;
  padding: 10px;
  margin: 10px;
  bottom: 0;
  right: 0;
  display: none;
  border-radius: 5px;
  z-index: 6;
  font-family: sans-serif;
}

.close {
  cursor: pointer;
  background: 0 0;
  border: 0;
  float: right;
  font-size: 21px;
  font-weight: 700;
  line-height: 1;
  color: #000;
  text-shadow: 0 1px 0 #fff;
  opacity: .2;
  position: absolute;
  right: 9px;
  top: 7px;
}

.close:hover {
  opacity: .5;
}

#popupText {
  margin-right: 23px;
}
Was this page helpful?