Skip to main content
Announcements
Qlik Connect 2024! Seize endless possibilities! LEARN MORE
Yianni_Ververis
Employee
Employee

In my previous post i explained how to use my template and build a website with Angular js and the Qlik Sense's Capabilities API.

Creating a website with Angular and the Capabilities API

When we build controllers with Angular and creating bindings among objects, on navigation, Angular is doing a very good job on managing the controllers, directives, services etc, but it does not handle properly the bindings from Qlik Sense. Thus, how ever many controllers and pages you may have, the objects that you have called with app.getObject(), are still there. That is why when you make a selection in one object and you navigate to another page, you get the "Error: [$compile:ctreq] Controller 'qv-collapsed-listbox-delegated-open', required by directive 'ngClass', can't be found!" error.

tutorial_2.png

Even though this does not affect the user experience, its still an error. Furthermore, if you have a large website with many object, as we usually do in our Demo and Best Practices Team, then this becomes a problem because there is memory allocation on each of the objects that were created with app.getObject().

Trying to solve it was a trivial process, since there is no documentation on how to destroy the objects. What I have done is, after the app.getObject() put a then(model), put the models into an array of objects and manage them on every page change. So I destroy all of them before I call $location with model.close() and then assign the new ones after the route has completed loading the new template and controller.

Let me explain the code change. I assume that you have already read on how to use the template Creating a website with Angular and the Capabilities API

  • Define the object array holder in our app.js

var me = {

  obj: {

       qlik: null,

       app: null,

       angularApp: null,

       model: [],

  }

};

  • In the html, put the usual code instead of the directive previously used. In dashboard.html replace L30 with this

<div class="qvobject" data-qvid="a5e0f12c-38f5-4da9-8f3f-0e4566b28398" id="a5e0f12c-38f5-4da9-8f3f-0e4566b28398"></div>

  • In our controller dashboard.js, replace L23 with the object array that we will call for binding,

me.objects = ['a5e0f12c-38f5-4da9-8f3f-0e4566b28398'];

  • In the same file, under the events, add the new function

me.getObjects = function () {

  api.getObjects(me.objects);

}

  • Now lets add the two functions in the API service. We need one function to create the objects and another one to destroy them

  me.getObjects = function (obj) {

       var deferred = $q.defer(),

       promises = [];

       angular.forEach(obj, function(value, key) {

            app.obj.app.getObject(value, value).then(function(model){

                 app.obj.model.push(model);

                 deferred.resolve(value);

            });

            promises.push(deferred.promise);

       });

       return $q.all(promises);

  };

  me.destroyObjects = function () {

       var deferred = $q.defer();

       var promises = [];

       if (app.obj.model.length >= 1) {

            angular.forEach(app.obj.model, function(value, key) {

                 value.close();

                 deferred.resolve();

                 promises.push(deferred.promise);

            });

            app.obj.model = [];

            return $q.all(promises);

       } else {

            deferred.resolve();

            return deferred.promise;

       }

  };

  • Finally, on every page change, call destroy objects and then move to the new page

  api.destroyObjects().then(function(){

       $location.url('/' + page);

  });

Make sure to check the latest code on

Git: https://github.com/yianni-ververis/capabilities-api-angular-template

Qlik Branch: http://branch.qlik.com/#/project/56b4a40140a985c431a64b08

2 Comments