Skip to main content
Announcements
Have questions about Qlik Connect? Join us live on April 10th, at 11 AM ET: SIGN UP NOW
cancel
Showing results for 
Search instead for 
Did you mean: 
savandriy
Contributor III
Contributor III

Require.js in Extension: Unable to add external js library

Hello Qlik Community,

I'm trying to load a library called jQuery-QueryBuilder, which is a jQuery plugin.

It has three main dependencies:  

- jQuery 3

doT.js

Query.extendext

I downloaded the respective files of the libraries, except jQuery, since it's already pre-installed with Qlik Sense Desktop.

The file structure (the extension is called "test"):

Documents\Qlik\Sense\Extensions\test:

  • libs:
    • doT.js
    • jquery-extendext.js
    • query-builder.js
  • test.js
  • test.qext
  • wbfolder.wbl

test.js:

 

define( [ 
	'qlik',
	'jquery',
	'./libs/doT',
	'./libs/jquery-extendext',
	'./libs/query-builder'
],

function (qlik, $, doT, extendext, builder) {

	return {
		support : {
			snapshot: true,
			export: true,
			exportData : false
		},
		paint: function ($element) {
			// some paint code...

                        //needed for export
			return qlik.Promise.resolve();
		}
	};
} );

 

But when trying to load them, I get some strange behavior. Using the Network tab in Chrome Developer Tools, I noticed that the files for 'doT' and 'jquery-extendext' are loaded twice.

The requests that succeeded had urls like 'http://localhost:4848/extensions/test/libs/doT.js', where the ones that failed had urls like 'http://localhost:4848/sense/dot/doT.js'.

I get errors in the console, saying:

 

Uncaught SyntaxError: Unexpected token '<'

 

And the files that failed contain HTML, and not js (looks like a blank Qlik page):

 

<!doctype html>
<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Qlik Sense</title>
    <meta charset="utf-8">
    <meta name="HandheldFriendly" content="True">
    <meta name="MobileOptimized" content="320">
    <meta name="viewport"
          content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,minimal-ui">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="format-detection" content="telephone=no">
    <meta http-equiv="cleartype" content="on">
    <base href="./">
    <link id="favicon" rel="shortcut icon" href="../resources/favicon.ico">
    <link rel="apple-touch-icon" href="../resources/img/core/logo/Sense_120x120.png">
    <link rel="apple-touch-icon" sizes="152x152" href="../resources/img/core/logo/Sense_152x152.png">
    <link rel="apple-touch-icon" sizes="167x167" href="../resources/img/core/logo/Sense_167x167.png">
    <link rel="apple-touch-icon" sizes="180x180" href="../resources/img/core/logo/Sense_180x180.png">
    <link href="../resources/app.6.212.5.css" rel="stylesheet">
</head>
<body role="application" class="qv-client">
<div class="qv-preload-icons" style="opacity: 0">.</div>
<div class="qv-preload-font" style="opacity: 0">.</div>
<div id="qv-init-ui-blocker"></div>
<div id="qv-page-container" class="qv-panel-wrap"></div>
<div id="addDataConnectorDialogContainer"></div>
<div id="dialogContainer"></div>
<script id="__set_assets_path">window.__DO_NOT_USE__ASSETS_URL = '../resources/';</script>
<script type="text/javascript" src="../resources/chunks/angular.da907af5a58359953a44.js"></script>
<script type="text/javascript" src="../resources/chunks/angular-lui.0db6f948f3f284cdce58.js"></script>
<script type="text/javascript" src="../resources/chunks/axios.11e425123b77dcc47ca7.js"></script>
<script type="text/javascript" src="../resources/chunks/es6-promise.a91da5fc9200aee58765.js"></script>
<script type="text/javascript" src="../resources/chunks/regenerator-runtime.8d8919a04c37e88f800f.js"></script>
<script type="text/javascript" src="../resources/chunks/jquery.0062d05e630bec82a23b.js"></script>
<script type="text/javascript" src="../resources/app.6.212.5.js"></script>
</body>
</html>

Experimenting, I figured out that the files that succeeded were the ones I manually defined in the 'define' section. The ones that failed, were internal dependencies of the 'query-builder' library:

 

/*!
 * jQuery QueryBuilder 2.5.2
 * Copyright 2014-2018 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
 * Licensed under MIT (https://opensource.org/licenses/MIT)
 */
(function(root, factory) {
    if (typeof define == 'function' && define.amd) {
        define(['jquery', 'dot/doT', 'jquery-extendext'], factory);
    }
    else if (typeof module === 'object' && module.exports) {
        module.exports = factory(require('jquery'), require('dot/doT'), require('jquery-extendext'));
    }
    else {
        factory(root.jQuery, root.doT);
    }
}(this, function($, doT) {
"use strict";

 

I tried multiple configuration options, using stuff like:

 

requirejs.config({
    paths:{
        "doT": "extensions/test/libs/doT",
		"jquery-extendext": 'extensions/test/libs/jquery-extendext'
    },
});

define( [ 
	'qlik',
	'jquery',
	'doT',
	'jquery-extendext',
	'./libs/query-builder'
],

 

But this breaks the succesful requests, generating urls like 'http://localhost:4848/sense/extensions/test/libs/doT.js'. And this didn't affect the internal dependencies at all 😞 

Can anyone please point me to a working config? 🙏

Labels (4)
1 Solution

Accepted Solutions
savandriy
Contributor III
Contributor III
Author

I think I've found a way around! And I might've figured what was the issue!

Looking for potential requirejs issues, I stumbled upon a post on stackoverflow.

In short, requirejs was looking for the nested dependencies in the wrong place.

I couldn't find a way to use relative path though, so I used CDN links. This is my working config:

requirejs.config({
  packages: [
    { name: 'dot', location: '//cdnjs.cloudflare.com/ajax/libs/dot/1.1.1', main: 'doT' },
	{ name: 'jquery-extendext', location: '//cdn.jsdelivr.net/npm/jquery-extendext@1.0.0', main: 'jquery-extendext' },
	{ name: 'query-builder', location: '//cdn.jsdelivr.net/npm/jQuery-QueryBuilder@2.5.2/dist/js', main: 'query-builder.min' },
  ]
});

define( [ 
	'qlik',
	'jquery',
  	'dot',
  	'jquery-extendext',
  	'query-builder'
],

It also works, if you specify the full path from localhost, as you suggested.

The only thing that worries me is if I'll be able to deploy this extension to the server.

Do you know if CDN links are allowed on the server version of Qlik?

 

View solution in original post

7 Replies
Aiham_Azmeh
Employee
Employee

Hi @savandriy ,

It's weird, an environment issue maybe - but it looks like a bug (please file one) - what version of Qlik Sense Desktop are you using?

 

savandriy
Contributor III
Contributor III
Author

Hi @Aiham_Azmeh ,

I'm using the currently latest Qlik Sense Desktop November 2019.

In the meantime, I would really like to start developing the extension. Do you think it's possible to use Webpack or some other tools to load the dependencies? Or maybe it's easier to try an older version of Qlik?

savandriy
Contributor III
Contributor III
Author

Ok, I've tried installing Qlik Sense Desktop June 2019, and it didn't change anything.

Aiham_Azmeh
Employee
Employee

Please file a bug.

A possible workaround  could be to use the full path:

define( [ 
  'qlik',
  'jquery',
  '//localhost:4848/extensions/test/libs/doT',
  '//localhost:4848/extensions/test/libs/jquery-extendext',
  '//localhost:4848/extensions/test/libs/query-builder'
],

Note: this is a theory, I haven't tested it.

savandriy
Contributor III
Contributor III
Author

I think I've found a way around! And I might've figured what was the issue!

Looking for potential requirejs issues, I stumbled upon a post on stackoverflow.

In short, requirejs was looking for the nested dependencies in the wrong place.

I couldn't find a way to use relative path though, so I used CDN links. This is my working config:

requirejs.config({
  packages: [
    { name: 'dot', location: '//cdnjs.cloudflare.com/ajax/libs/dot/1.1.1', main: 'doT' },
	{ name: 'jquery-extendext', location: '//cdn.jsdelivr.net/npm/jquery-extendext@1.0.0', main: 'jquery-extendext' },
	{ name: 'query-builder', location: '//cdn.jsdelivr.net/npm/jQuery-QueryBuilder@2.5.2/dist/js', main: 'query-builder.min' },
  ]
});

define( [ 
	'qlik',
	'jquery',
  	'dot',
  	'jquery-extendext',
  	'query-builder'
],

It also works, if you specify the full path from localhost, as you suggested.

The only thing that worries me is if I'll be able to deploy this extension to the server.

Do you know if CDN links are allowed on the server version of Qlik?

 

Aiham_Azmeh
Employee
Employee

Yes, you can use CDN's - but be aware that it may make your extension "un-printable" (https://help.qlik.com/en-US/sense-developer/September2019/Subsystems/Extensions/Content/Sense_Extens...).

 

savandriy
Contributor III
Contributor III
Author

Cool, thanks a lot 👍