Skip to main content
Announcements
Qlik Connect 2024! Seize endless possibilities! LEARN MORE
cancel
Showing results for 
Search instead for 
Did you mean: 
frankpacker_AoD
Contributor II
Contributor II

Building a JavaScript array by paging through HyperCube pages in AngularJS extension

Hi All,

Hoping for some help with building a big JavaScript object from a HyperCube that goes to more than 10000 cells.

It's a straightforward AngularJS extension, and I've found the article for retrieving extra data here: https://help.qlik.com/en-US/sense-developer/May2021/Subsystems/Extensions/Content/Sense_Extensions/H...

The issue I have is that I don't really want to call my paint function for every page of the HyperCube. What I actually want to do is build a chunky JavaScript array of all the data that I can then operate on to use in my template.

Basically, at the end of the day, I'm trying to work out the best method to loop through all pages of the huge HyperCube in a single execution of paint so that I can modify the structure of the data to suit the needs of the extension.

I've added comments to the code here to better explain what I'm trying to achieve.

define([
  "qlik",
  "jquery",
  "text!./style.css",
  "text!./template.html",
], function (qlik$cssContenttemplate) {
  "use strict";
  $("<style>").html(cssContent).appendTo("head");
  return {
    template: template,
    initialProperties: {
      qHyperCubeDef: {
        qDimensions: [],
        qMeasures: [],
        qInitialDataFetch: [
          {
            qWidth: 20,
            qHeight: 500,
          },
        ],
      },
    },
    definition: {
      type: "items",
      component: "accordion",
      items: {
        dimensions: {
          uses: "dimensions",
          min: 6,
          max: 6,
        },
        measures: {
          uses: "measures",
          min: 0,
          max: 14,
        },
        sorting: {
          uses: "sorting",
        },
        settings: {
          uses: "settings",
        },
      },
    },
    support: {
      snapshot: true,
      export: true,
      exportData: true,
    },

    paint: function ($elementlayout) {
 
    //this block is from the above link
      var lastrow = 0me = this;
      var resultTable = [];
      this.backendApi.eachDataRow(function (rownumrow) {
        lastrow = rownum;
        resultTable.push(row); //can push each row into my table and that does work ok, but requires a repaint for every iteration and means that I can't operate on the output table because of the delay in promises returning
        
      });

      if (this.backendApi.getRowCount() > lastrow + 1) {
        var requestPage = [
          {
            qTop: lastrow + 1,
            qLeft: 0,
            qWidth: 20
            qHeight: Math.min(500this.backendApi.getRowCount() - lastrow),
          },
        ];
        this.backendApi.getData(requestPage).then(function (dataPages) {
          me.paint($element);
        });
      }

  
    console.log("resultTable"resultTable); //I want to wait for the completed dataset (so, wait for the promises to return) when the paint gets called. 
    
  },
    controller: ["$scope"function ($scope) {

    }],
  };
});
 
 
Any help would be appreciated!
 
Labels (5)
1 Solution

Accepted Solutions
frankpacker_AoD
Contributor II
Contributor II
Author

Ok, solved it.

This needs to be set: this.backendApi.setCacheOptions({enabled: false});
 
The cache option on backendApi means that you can't do async calls to it.

View solution in original post

2 Replies
frankpacker_AoD
Contributor II
Contributor II
Author

I've made some progress on this, and think I'm nearly where I need to be with it, but there's still a small problem I hope someone can help me with, or tell me where I'm off track.

This is my paint function, now:

code.jpg

I'm running a loop to build the page requests for each execution of backendApi.getData, pushing the promises into an array then executing them with Promise.all

Logging the array thePromises to the console produces the below, which superficially looks fine:

console.jpg

but the following error is thrown from the Promise.all function call:

error.jpg

Further examination of the promises in the array reveals the cause:

opened_promises.jpg

I can confirm that executing just the first promise from the array works ok, like this:

execution.jpg

So does executing it twice in an array:

Untitled-15.jpg

So, something's not working properly in the loop that builds the array, and the second iteration is not receiving the backendApi.getData promise correctly.

Is this an issue with reference typing, or something else to do with my understanding of this particular promis object?

Can anyone help with how to get this last part over the line?

frankpacker_AoD
Contributor II
Contributor II
Author

Ok, solved it.

This needs to be set: this.backendApi.setCacheOptions({enabled: false});
 
The cache option on backendApi means that you can't do async calls to it.