Loading custom js and css

Unfortunately it doesn’t look like I can use @Javascript and @CssImport to load local non-frontend resources.
Thankfully, Matti has recently addressed that in a blog post: https://vaadin.com/blog/building-java-api-for-javascript-libraries

The pattern he uses is something like this:

public class MyStuff extends Div {
    
    public MyStuff() {}
        boolean loaded = ui.getElement().getProperty("mystuff-loaded", false);
        if(!loaded) {
            ui.getPage().addJavaScript("/some/local/path/mystuff.js");
            ui.getElement().setProperty("mystuff-loaded", true);
        }
    }

}

I’ve generalized this to a loadJs(String path) which loads the path and also use the path as property name.
This works fine in both Firefox and Chrome, but I feel a bit uneasy about it.
Does anyone know if there are any limitations on a “property” name, or is it just a string in a hash table?

It’s a property in the body element in your browser. I’m not sure what you’re thinking when you are talking about limitations

But I’m unclear on what that is
If it is a regular javascript object property, then I assume almost anything is ok.
So, I can do ui.getElement.setProperty(“>”, true) without breaking anything?

I wouldn’t try to put > in a property so I don’t know the result

“>” was just there to take it to the extreme, to understand what the limits are, if any. For now I’ll assume it is a javascript object property, ie a hash-key, and that almost anything is allowed, even “>”, and certainly a resource path, so there should be no issue doing:

public void loadJs(UI ui, String path) {
    boolean loaded = ui.getElement().getProperty(path, false);
    if(!loaded) {
        ui.getPage().addJavaScript(path);
        ui.getElement().setProperty(path, true);
    }
}

That seems to me overkill. How many JavaScript files are you loading? You can use one flag for all the JavaScript files. Maybe @quintessential-ibex knows the answer.

We have hundreds of screens. Most using just regular Vaadin components, but a handful use Highchart, both regular and Gantt, and Leaflet Map.
Now that we are free from the yoke that was GWT I can easily imagine us using other javascript frameworks as well. Hopefully through Web Components, and ready-made Vaadin integration, but I can’t assume that.

One of the special screens now has:

var vaadinComponent = new CustomComponent()
    .loadJs("/ptsmc/map/plugins/js/leaflet.min.js")
    .loadJs("/ptsmc/map/plugins/js/jquery-3.6.0.min.js")
    .loadJs("/ptsmc/map/plugins/js/autocomplete.min.js")
    .loadJs("/ptsmc/map/plugins/js/map.js")
    .loadJs("/ptsmc/map/plugins/js/customized-rotatedMarker.js")
    .loadJs("/ptsmc/map/plugins/js/fullscreen.js")
    .loadJs("/ptsmc/map/plugins/js/customized-search.js")
    .loadJs("/ptsmc/map/plugins/js/customized-bookmark.js")
    .loadJs("/ptsmc/map/plugins/js/leaflet.contextmenu.min.js")
    .loadJs("/ptsmc/map/plugins/js/lodash.js")

    .loadCss("/ptsmc/map/plugins/css/customized-leaflet.css")
    .loadCss("/ptsmc/map/plugins/css/autocomplete.css")
    .loadCss("/ptsmc/map/plugins/css/customized.css")
    .loadCss("/ptsmc/map/plugins/css/autocomplete.css")
    .loadCss("/ptsmc/map/plugins/css/customized-fullscreen.css")
    .loadCss("/ptsmc/map/plugins/css/customized-bookmarks.css")
    .loadCss("/ptsmc/map/plugins/css/leaflet.contextmenu.min.css")
    
    .executeJs("initMap('" + getMapVariant() + "');");

I haven’t written the screen, so I have no idea which of these can be considered part of the same “package”, so it is less error-prone to have a flag for each.

I assume this could be “frontended”, but I just want to get stuff done.

With @JavaScript and @StyleSheet annotations you can dynamically load local CSS and JS files from resources using “context://” prefix, see example here pivot-table-flow/src/main/java/org/vaadin/addons/componentfactory/PivotTable.java at v23 · vaadin-component-factory/pivot-table-flow · GitHub

And files in resources

E.g. it was necessary in the above example, as the library used is not proper ES module, and Vite does not like it.