6 Replies Latest reply: Dec 14, 2017 9:34 AM by Mark Guthrie RSS

    Qlik sense API question

    Mark Guthrie

      I am trying to write a visual extension for as a test for an app I want to build here for work. I normally work with C# so most of the angular stuff is still really new to me. I am trying to retrieve a listing of the current pages in the current working app. I can call the app.getList() function with the 'sheet' parameter and it seems to work fine. However when I try to bind to the scope object it seems like it is never populated with anything. This is the current initial code I am using. When I check the console sheetlist is populated with all of the sheets in the app but when i bind the sheets variable in the template it doesn't do anything. Any help from you guys would be most appreciated. Am I doing this completely wrong?

       

      define( [

      'jquery',

      './properties',

      'text!./template.ng.html',

      'qlik'

      ],

      function ( $, props, ngTemplate, qlik ) {

      'use strict';

      return {

      definition: props,

      initialProperties: {},

      snapshot: {canTakeSnapshot:true},

      template: ngTemplate,

      controller: ['$scope', function($scope){

      $scope.myTitle = "This is my angularJS menu";

      var app = qlik.currApp();

      $scope.sheets = app.getList('sheet', function(reply){

      var sheetList = [];

      $.each(reply.qAppObjectList.qItems, function (key, value) {

      sheetList.push({sheetId: value.qInfo.qId, sheetName: value.qData.title});

      });

      console.log('sheetlist', sheetList);

      return sheetList;

      });

      }]

      };

      } );

       

      Here is what i am using to test for the template.

      <div qv-extension>

      <b ng-bind="myTitle"/>

      <pre ng-repeat="(key, val) in this">{{key}} = {{val|json}}</pre>

      <b ng-repeat="sheet in sheets"><br />{{sheet}}</b>

      </div>

        • Re: Qlik sense API question
          Jesper Snihs

          Hi Mark,

          You don't use return in your controller to pass variables to the template, you just assign them to the $scope variable. For example if you want to use a variable in the template called sheetlist, you assign the variable in the controller as $scope.sheetlist.

           

          I did a few changes to your code and made it work.

           

          define( [
                  'jquery',
                  './properties',
                  'text!./template.html',
                  'qlik'
              ],
              function ( $, props, ngTemplate, qlik ) {
                  'use strict';
          
                  return {
                      definition: props,
                      initialProperties: {},
                      support: {
                          snapshot: false,
                          export: false,
                          exportData: false
                      },
                      template: ngTemplate,
                      paint: function ($element, layout) {
                          return qlik.Promise.resolve();
                      },
                      controller: ['$scope', function($scope){
                          $scope.myTitle = "This is my angularJS menu";
                          var app = qlik.currApp();
                          app.getList('sheet', function(reply){
                              $scope.sheetList = [];
                              $.each(reply.qAppObjectList.qItems, function (key, value) {
                                  $scope.sheetList.push({sheetId: value.qInfo.qId, sheetName: value.qData.title});
                              });
                          });
                      }]
                  };
              });
          

           

          <div qv-extension style="height: 100%; position: relative; overflow: auto;" class="ng-scope">
              <b ng-bind="myTitle"/>
              <pre ng-repeat="(key, val) in this">{{key}} = {{val|json}}</pre>
              <b ng-repeat="sheet in sheetList"><br />{{sheet.sheetName}}</b>
          </div>
          

           

          Just make sure when you test this if you just paste this code in your original extension, remove your extension object from the sheet, reload and then add it back again.

          • Re: Qlik sense API question
            Erik Wetterberg

            Hi Mark,

            Don't use getList in your extension, at least avoid it in rendering. It's better to add the data you need to the underlying generic object by adding the sheet list to initialProperties, something like this:

            initialProperties: {
              qAppObjectListDef: {
                 qType: 'sheet'
              }
            }
            

             

            You will then find the list of sheet in the layout. You don't have to handle the asynchronity, the client framework will do that for you and your extension might be snapshottable. You might need to include a qData property too, to get the fields you want.

             

            You fin documentation for qAppListObjectDef here

             

            More on generic objects:Introduction to Generic Object

             

            Hope this helps

             

            Erik Wetterberg

              • Re: Qlik sense API question
                Jesper Snihs

                Erik's answer is a much better solution.

                As Erik wrote you will find the sheets in the layout, but since you said that you are pretty new to extensions, this might not be completely clear where this is. So I will just point out where you will find the sheets to make it a bit easier.

                 

                If you are in the controller you will find them in $scope.layout.qAppObjectList.qItems.

                 

                Regards

                • Re: Qlik sense API question
                  Mark Guthrie

                  Erik I seem to be having an issue with this. If i don't add a qData I dont actually see anything returned in my layout object. When I add qdata to the definition the extension doesn't seem to want to compile and the extension stops working in my test app. this was how I was setting it up in my initial properties file.

                   

                  // JavaScript

                  define( [], function () {

                      'use strict';

                      return {

                     qAppObjectListDef: { 

                     qType: 'sheet',

                     qData: {}

                    }

                      };

                  } );

                   

                  I also tried adding in stuff in the qData portion such as qData: {id : qInfo.qId} which is how I think its supposed to be declared from the documents you linked but the same issue is occurring.

                    • Re: Qlik sense API question
                      Erik Wetterberg

                      Hi Mark,

                      If you have got a qAppObjectListDef in your properties you should always get a qAppObjectList in your layout, and since you will always have at least one sheet in you app it should have at least one entry.

                       

                      But for the initialProperties changes to have effect you need to recreate (or convert) your extension object. So create a new one and see what happens.

                       

                      The list you get will always contain the sheet id (under qInfo.qId) but might not contain the sheet title. If not you would use qData to get it, like this:

                      qData:{
                        title:'/title'
                      }
                      

                      Meaning that you want a property called title and in it you should have the value stored at the path '/title'.

                       

                      Hope this helps

                       

                      Erik Wetterberg