How to use external Javascript libraries correct in Vaadin 14 NPM ?

I’m trying to figure out how to use external javascript libraries in Vaadin 14.0.3 with Spring Boot.

I was able to call my own javascript functions by defining them with window sope ([see other forum entry]
(https://vaadin.com/forum/thread/17828571/javascript-not-importing-correctly-vaadin-14-npm)):

window.showAlert = function(){
    alert('test');
};

However for external libraries I can’t modify any code. How do i call functions of libraries I imported the following way:

@JavaScript("./src/frameworks/echarts-en.min.js")
public class MainLayout extends Div implements ...

In Vaadin 13 (14 bower mode) everything just worked with simply importing normal javscript files. Would be nice if there would be an updated guide for Vaadin 14 NPM.

In NPM mode @JavaScript works in the same way as @JsModule (for “local” java scripts) which means
that the JS will be included in the common bundle within its own scope.
So all variables defined in the file will be scoped (not in global scope) and you won’t be able
to use them out of this scope.
The workaround is using the scope explicitly (like window.xxx) or use module imports (import one module from another).

@JavaScript should still work as before for external JS (http://extrnalurl).
Also you may use programmatic way of add java script via Page::addJavaScript . In this case the javascript
won’t be compiled into a bundle but should be added as a standalone JS so it should work as previously.

I’m not sure whether this is documented properly.
Please create a ticket about documentation if it’s not.

Thanks for the answer,
i imported it the follwing way:

ui.getPage().addJavaScript("frontend://src/frameworks/echarts-en.min.js");

When i import it this way, i can call the library functions.

Hello,

I am trying to integrate vis-network (Version 6.4.7) module into Vaadin 14. For this I use the following annotations:

@JsModule("vis-network/dist/vis-network.js")
@CssImport("vis-network/styles/vis-network.min.css")
@NpmPackage(value = "vis-network", version = "6.4.7")

Then I try to execute Javascript from Java:

page.executeJs(" var data = {nodes:new vis.DataSet...

I then get the following error:
Uncaught ReferenceError: vis is not defined

I already tried window.vis, but unfortunately I get the same error. What could be the reason?

Greets,
Benjamin

Hi,

You can add a javascript that load the library and define window.vis.

Here an example with a tooltip: https://github.com/jcgueriaud1/vaadin-tooltip-js/blob/master/frontend/src/tooltip-loader.js

and the Java class: https://github.com/jcgueriaud1/vaadin-tooltip-js/blob/master/src/main/java/org/vaadin/jeanchristophe/global/WindowResourceView.java

And the reason is:
Vaadin 14 loads your JavaScript as a JS Module, which means that it runs in strict mode. With strict mode, it’s an error to reference a variable that isn’t declared. Without strict mode, it’s treated as a global variable. When running in the browser, the top-level window object which represents the browser window (or tab) is used for storing global variables.

(from here: https://vaadin.com/forum/thread/17753553/can-t-use-frontend-js-with-vaadin-14)

I’m trying to use an online api in window scope.
I tried your solution and did the following:

window.Stripe = require("https://js.stripe.com/v3");

Sadly when starting the node server throws this error:

2019-12-16 22:21:23.321 ERROR 20724 --- [        webpack]
 dev-webpack                              : ERROR in ./src/javascript/stripe.js
2019-12-16 22:21:23.321 ERROR 20724 --- [        webpack]
 dev-webpack                              : Module not found: Error: Can't resolve 'https://js.stripe.com/v3' in 'C:\ ... \frontend\src\javascript'
2019-12-16 22:21:23.321 ERROR 20724 --- [        webpack]
 dev-webpack                              :  @ ./src/javascript/stripe.js 17:16-51
2019-12-16 22:21:23.321 ERROR 20724 --- [        webpack]
 dev-webpack                              :  @ ../target/frontend/generated-flow-imports.js

Is there any way how i can import a framework from a web adress and declare it global?

Hi,

You can load it from the Java using @Javascript annotation as it’s external file.
Then in your javascript the Stripe object should be available.

Here the example with an external js: https://github.com/jcgueriaud1/vaadin-tooltip-js/blob/master/src/main/java/org/vaadin/jeanchristophe/external/ExternalResourceView.java

Thanks, that worked for the external URL (I thought i tried this earlier but back then it did not work).

Another question related back to your original answer:

I implement a JS Library in my MainLayout the following way:

@JsModule("./src/frameworks/echarts-en.min.js") //library
@JsModule("./src/javascript/echart.js") //custom code
...

Now in the echart.js i want to define the libary entry point global:

window.echarts = require("echarts-en.min.js");

...
//some functions which need to call echart.init(...)
...

Node Error Messsage when starting:

2019-12-17 20:02:28.972 ERROR 20308 --- [        webpack]
 dev-webpack                              : ERROR in ./src/javascript/echart.js
2019-12-17 20:02:28.972 ERROR 20308 --- [        webpack]
 dev-webpack                              : Module not found: Error: Can't resolve 'echarts-en.min.js' in 'C:\ ... \frontend\src\javascript'
2019-12-17 20:02:28.972 ERROR 20308 --- [        webpack]
 dev-webpack                              :  @ ./src/javascript/echart.js 4:16-44
2019-12-17 20:02:28.972 ERROR 20308 --- [        webpack]
 dev-webpack                              :  @ ../target/frontend/generated-flow-imports.js

Sadly this is not working. How do i have to define the path to get this working?

Probably doing this:
window.echarts = require(“…/frameworks/echarts-en.min.js”);

But I’m not sure if I understand correctly where your js files are :slight_smile:

Thanks again! That is the correct path.

Benjamin Requardt:
Hello,

I am trying to integrate vis-network (Version 6.4.7) module into Vaadin 14. For this I use the following annotations:

@JsModule("vis-network/dist/vis-network.js")
@CssImport("vis-network/styles/vis-network.min.css")
@NpmPackage(value = "vis-network", version = "6.4.7")

Then I try to execute Javascript from Java:

page.executeJs(" var data = {nodes:new vis.DataSet...

I then get the following error:
Uncaught ReferenceError: vis is not defined

I already tried window.vis, but unfortunately I get the same error. What could be the reason?

Greets,
Benjamin

Did you ever get the visJS libary working with vaadin 14 and the @NpmPackage annotation
Because I am trying the same now with:

@NpmPackage(value = "vis-timeline", version = "7.4.2")
@StyleSheet("vis-timeline/dist/vis-timeline-graph2d.css")
@JavaScript("vis-timeline/dist/vis-timeline-graph2d.min.js")

And getting the “(ReferenceError) : vis is not defined”

Jonas TM:
I’m trying to use an online api in window scope.
I tried your solution and did the following:

window.Stripe = require("https://js.stripe.com/v3");

Sadly when starting the node server throws this error:

2019-12-16 22:21:23.321 ERROR 20724 --- [        webpack]

dev-webpack : ERROR in ./src/javascript/stripe.js

2019-12-16 22:21:23.321 ERROR 20724 — [ webpack]
dev-webpack : Module not found: Error: Can’t resolve ‘https://js.stripe.com/v3’ in ‘C:\ … \frontend\src\javascript’
2019-12-16 22:21:23.321 ERROR 20724 — [ webpack]
dev-webpack : @ ./src/javascript/stripe.js 17:16-51
2019-12-16 22:21:23.321 ERROR 20724 — [ webpack]
dev-webpack : @ …/target/frontend/generated-flow-imports.js


Is there any way how i can import a framework from a web adress and declare it global?

Did you ever get stripe to work? The reason I ask is because of this:

https://vaadin.com/forum/thread/18480598/typeerror-in-safari