904
Views
18
Comments
Solved
Load external JS in Outsystems Reactive Web App

Hi there!

I'm trying to load an external js file into an OutSystems Reactive Web App Module inside of a personal development environment.

The script I need to load inside the page is: <script src="//channel.me/frameconnect.js"></script>

Currently, I got it to load inside of a <span> element on the page, but even though the script shows inside the page source, it doesn't load when I look at which .js files are loaded.

Is there a different way in which I should be adding the script?

Thanks in advance!
Marleen Renders

Rank: #378
Solution

Hi Marleen,

I would suggest to download the file and add it to the resources. After that you just need to add it to the pages where you need that specific library. Check this documentation here and also the master class with videos here.

Notice this is the best way to do it, since those websites could get under attack of malwares and in the future can be putting things not desired into your website. It can also be updated to other versions that can break something that is now working.

Cheers!

Rank: #6239

Thanks Tiago. I've included the .js file, this works and the file is loaded.

I have another question, but I will add a new topic for that, since it doesn't fall under the scope of this question.


Thanks again!
Marleen

mvp_badge
MVP
Rank: #113

I am also looking for same solution for problem is that I want to load google map js which needs API key as query string parameter. So it is not possible to save js file and include in my project. 

So is there any other way to add external script reference to reactive web app?

mvp_badge
MVP
Rank: #47

Hi Nikhil Gaur,

You can add into the OnInitialize event of your screen this javascript below 


var head1 = document.getElementsByTagName('head')[0];
var script_src1= "your_js_url_with_parameters";
var new_script1 = document.createElement('script');
new_script1.type = 'text/javascript';
new_script1.src= script_src1;
head1.appendChild(new_script1); 


Regards

Fabio


Rank: #1803

Fábio Fantato wrote:

Hi Nikhil Gaur,

You can add into the OnInitialize event of your screen this javascript below 


var head1 = document.getElementsByTagName('head')[0];
var script_src1= "your_js_url_with_parameters";
var new_script1 = document.createElement('script');
new_script1.type = 'text/javascript';
new_script1.src= script_src1;
head1.appendChild(new_script1); 


Regards

Fabio


Hi Fabio,

what if I'm creating a web block? Because I don't have the OnInitialize on a web block?

I'm trying to integrate Google's reCAPTCHA checkbox and I need to reference a script library and there are some parameters on the script's url that I need to set them dynamically (onload, render, locale)


<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"
    async defer>
</script>

thanks

Ricardo


mvp_badge
MVP
Rank: #113

Ricardo Costa wrote:

Fábio Fantato wrote:

Hi Nikhil Gaur,

You can add into the OnInitialize event of your screen this javascript below 


var head1 = document.getElementsByTagName('head')[0];
var script_src1= "your_js_url_with_parameters";
var new_script1 = document.createElement('script');
new_script1.type = 'text/javascript';
new_script1.src= script_src1;
head1.appendChild(new_script1); 


Regards

Fabio


Hi Fabio,

what if I'm creating a web block? Because I don't have the OnInitialize on a web block?

I'm trying to integrate Google's reCAPTCHA checkbox and I need to reference a script library and there are some parameters on the script's url that I need to set them dynamically (onload, render, locale)


<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"
    async defer>
</script>

thanks

Ricardo


You are using web block which means you are developing traditional web application that is why you don't have OnInitialize. 

In that case you can add script reference using AddJavaScriptTag server action in the prepration of your web block.

Rank: #381

Hello Fabio,


Is this the only way to add reference to external scripts right now in Reactive web? It seems a little convoluted in what should be every day bread-and-butter for web development (ran into this issue trying to implement Google Analytics). 


Downloading scripts works but I don't think that should be the way either, it's cluttering your app with unnecessary files, where you could keep the Script location in a site property and then update it there when a new version comes out, without having to redeploy the whole application.


Hopefully there will be an easier and better way to do this?

Rank: #499

Mariano Picco wrote:

Hello Fabio,


Is this the only way to add reference to external scripts right now in Reactive web? It seems a little convoluted in what should be every day bread-and-butter for web development (ran into this issue trying to implement Google Analytics). 


Downloading scripts works but I don't think that should be the way either, it's cluttering your app with unnecessary files, where you could keep the Script location in a site property and then update it there when a new version comes out, without having to redeploy the whole application.


Hopefully there will be an easier and better way to do this?

 

 I agree, very definition of spaghetti code.
I am struggling to add script tags with custom attributes.
Such simple task to do but very hard to do on the platform.

mvp_badge
MVP
Rank: #113

Hi Mariano,

You are right, even I feel that downloading and adding each script in the application is not a good option and there sould be a better way to do this.

For example in Treditional web apps we can add script reference using AddJavaScriptTag server action.

mvp_badge
MVP
Rank: #17

I agree with Tiago's solution, you need to be as less as possible dependent on external sites for reasons of availability, malicious attacks or updates that contain breaking changes or bugs.

This requires extra factory management effort to keep up with the latest versions of external libraries, but with the big benefit that you are in control and that you can test external library update prior to pushing it to production.

Rank: #381

Daniël Kuhlmann wrote:

I agree with Tiago's solution, you need to be as less as possible dependent on external sites for reasons of availability, malicious attacks or updates that contain breaking changes or bugs.

This requires extra factory management effort to keep up with the latest versions of external libraries, but with the big benefit that you are in control and that you can test external library update prior to pushing it to production.

How is keeping the URL of the library in a site property not a better approach, with the added advantage of not having to republish a solution just because a new version of a library came out? Specially when modern websites can use a dozen of these easily.


mvp_badge
MVP
Rank: #17

Mariano Picco wrote:

How is keeping the URL of the library in a site property not a better approach, with the added advantage of not having to republish a solution just because a new version of a library came out? Specially when modern websites can use a dozen of these easily.

You are assuming here that the external library has version numbering in their URL. In that case you are right, you could be better of. Then again if the new version contains breaking changes, you might still neeed to republish.

BTW, OutSystems UI and OutSystems UI web follow the approach as described by Tiago.


Rank: #381

Daniël Kuhlmann wrote:

You are assuming here that the external library has version numbering in their URL. In that case you are right, you could be better of. Then again if the new version contains breaking changes, you might still neeed to republish.

BTW, OutSystems UI and OutSystems UI web follow the approach as described by Tiago.



Yes, and this is how there are OutSystems applications floating around with extremely vulnerable versions of jQuery and other things. I do not think this is good practice. I rather have a bit of code not working because of breaking changes than a penetration testing report coming back to our clients saying the website we built them includes javascript code susceptible to XSS attacks (and yes, it has happened, made us look quite badly in their eyes).

mvp_badge
MVP
Rank: #17

Hi Mariano,

When using versioned external libraries from something like Google's CDN I can see your point.

But if the external library is not versioned and not from a CDN I beg to differ.

Regarding your comment of vulnerable versions of jQuery floating around, that is just poor factory management.

Either way if you include libraries (and have to manage updates yourself) or use links to external libraries,,it remains the responsible of the development team/company to follow best practices regarding performance, security, maintainabillity and realiabillity. .

Regards,

Daniel

Rank: #381

I think there's a stark contrast between going into Service Center and having someone change the URL for a property rather than someone going into Service Studio, having to delete the old version of the file, uploading a new one, publishing, recompiling the whole solution, pushing it to the live environment... 

Agree to disagree I guess. I still think there should be a proper way to do this.

Staff
Rank: #5692

Hi,

I think we are missing here a client action that is given by the system which is RequireScript (https://success.outsystems.com/Documentation/11/Reference/OutSystems_APIs/System_Actions#RequireScript).

You can use this client action to add the required script URL to the header of the page. I would try to add it to the OnInitialize event.



Rank: #28416

Rodolfo Cardoso wrote:

Hi,

I think we are missing here a client action that is given by the system which is RequireScript (https://success.outsystems.com/Documentation/11/Reference/OutSystems_APIs/System_Actions#RequireScript).

You can use this client action to add the required script URL to the header of the page. I would try to add it to the OnInitialize event.



 This is the perfect solution for us. We were trying to use the Square API (for security purposes square requires us to use the script remotely hosted on their servers). The download of the .js file was not even a option.

 

Staff
Rank: #1273

Hi all,

The solution to use RequireScript by Jordan is correct. However, if you need flexibility to add attributes to the <script> tag or just want to use the traditional injection method, I found out how to make it work for some scripts which don't appear to load correctly. I think due to the asynchronous nature of Reactive Web apps, the mechanism of executing the this external library is different than normal. 

You can add the attribute "data-os-finished" with a value of "true". It seems that Reactive Web is detecting this attribute to process scripts. My best guess is that on render event visits the scripts that have that attribute. I haven't been able to fully confirm how that attribute works. Nevertheless, it means that if you want to use the injection method described above, you only have to add that attribute for it to work. Without the attribute, the <script> tag is injected but it does not execute.

This will work if you don't want to use RequireScript:

var head1 = document.getElementsByTagName('head')[0];
var new_script1 = document.createElement('script');
new_script1.type = 'text/javascript';
new_script1.src = "your_js_url.js?params=" ;
new_script1.setAttribute ("data-os-finished", "true");
new_script1.charset = "utf-8";
head1.appendChild(new_script1);

I hope that will help someone down the line.