Reputation: 197
I'm trying to develop my first Vaadin 14 application, I'm also using Spring boot framework for it.
I've created a javascript file, I put it into the folder frontend/src with the name of teams.js and I'm trying to import it with @JsModule("src/teams.js")
. My root view class looks like this:
@Route("")
@PageTitle("Teams organization store init")
@Slf4j
@JsModule("src/teams.js")
@Tag("TeamsEntry")
public class TeamsEntryView extends VerticalLayout implements BeforeEnterObserver {
public TeamsEntryView() {
initTeams();
}
private void initTeams() {
var ui = UI.getCurrent();
var page = ui.getPage();
log.info("Teams initialization...");
page.executeJs(getTeamsConfig()).toCompletableFuture().whenComplete(((jsonValue, throwable) ->
log.info("Teams initialization completed: {} with throwable {}", jsonValue.toJson(), throwable.getMessage())
));
}
private String getTeamsConfig() {
return """
console.log('ss');
window.initTeams();
console.log('xx');
return true;
""";
}
...
My js file looks like this:
window = {
initTeams: function () {
console.log('initTeams...');
}
}
In this case, I see "ss" in the browser's console, but nothing more.
If I remove the window.initTeams();
line I get "ss" and "xx" as well.
If I declare a simple function in the js file and call it without the "window" class I get similar results.
If I use @Javascript
or page.addJavascript("src/teams.js")
I get this error when the page loads: "> unexpected character"
If I try to call join()
or get()
on the completable future the browser freeze.
If I use @Javascript("frontend://src/teams.js")
I get some CORS error like if it is trying to download something from the "frontend" host.
I've tried to put the @JsModule
on a component instead of my view.. it does not work.
I've tried to put my js file to the root, and to the resources folder.
I could not find any other solution to import and use my js file into vaadin14 with spring boot. Also, I'm not sure why the browser freeze if I call "join()" on completable future, and also the on the result of it sentToBrowser returns false even if I see the console logs in the browsers log...
Can somebody explain to me how should I do the javascript import, why my current code does not work, and why the "join()" freezes the browser, please?
Thank you in advance!
@Edit
I have also tried with this annotation @JavaScript("./src/teams.js")
and a js like this:
function initTeams () {
console.log('initTeams...');
console.log("Teams initialized!")
}
@Edit
Okay so finally I got it working.
The js file has to be under root/src/main/webapp/src
folder.
Nor @JavaScript
and nor the @JsModule
worked for me, so I had to import my js file as:
var ui = UI.getCurrent();
var page = ui.getPage();
page.addJavaScript("src/teams.js");
Then I can call it like window.initTeams()
or like initTeams()
and both works fine. Altough the completable future below still never executes, and isSentToBrowser()
always returns false.
page.executeJs(getTeamsConfig()).toCompletableFuture().whenComplete(((jsonValue, throwable) ->
log.info("Teams initialization completed: {} with throwable {}", jsonValue.toJson(), throwable.getMessage())
));
I must mention if I start the path with '.' like page.addJavaScript(".src/teams.js");
then it does not find the file.
Does anybody have an answer, why the completable future never executes?
Upvotes: 3
Views: 664
Reputation: 1645
The problem is that the following code redefines the window
object:
window = { initTeams: function () { console.log('initTeams...'); } }
Did you meant to add a function to the window
object? Like so:
window.initTeams = function () {
console.log('initTeams...');
};
If you want to keep code visually similar to yours:
window = {
...window,
{
initTeams: function() {
console.log('initTeams...');
}
}
}
Other options:
window['initTeams'] = function() {...}
Object.assign(window, {initTeams: function() {...}})
Object.defineProperty(window, 'initTeams', {value: function() {console.log('foo')}});
Gotta love JavaScript...
Also, for more knowledge, the code mentioned in your @Edit section could not be called. Calling initTeams()
is equivalent to window.initTeams()
. The function must exist in the window
object. This is why, for example, you see some custom elements defined like customElements.define(...)
and window.customElements.define(...)
.
Upvotes: 3