javascriptjavajavafxjavafx-webengine

How to Call to a UI variable of JavaFX from javascript in WebEngine?


I'm working on an application that needs to read a local file and display it in WebView, based on user input (in ComboBox). I'm trying to call to a variable in the JavaFX UI from JavaScript and it doesn't work.

I created a function called getMonthIndex() in the Java code that returns the input of the ComboBox and that the file should be received with the appropriate name. I'm trying to import this function into the JavaScript code, and it doesn't seem to be included in the JavaScript code.

If you can explain to me how to get a parameter from the JavaFX UI and use it within the JavaScript code.

Thanks so much in advance for any help you can.

My Controller.java:

public class Controller {

    ObservableList<String> months = FXCollections.observableArrayList
                    ("Tishrei", "Cheshvan", "Kislev", "Tevet", "Shevat", "Adar",
                    "Nisan", "Iyar", "Sivan", "Tammuz", "Av", "Elul");

    public ComboBox<String> month;
    public WebView webView;

    public String getMonthIndex() {
        ReadOnlyIntegerProperty listIndex = month.getSelectionModel().selectedIndexProperty();
        return String.format("%02d", listIndex.getValue());
    }

    public long linesCount(String scanFile) {
        if (scanFile.length() < 80) {
            return scanFile.length() / 15;
        } else {
            return scanFile.length() / 24;
        }
    }

    @FXML
    public void initialize() {
        month.setItems(months);

        webView.setContextMenuEnabled(false);

        WebEngine webEngine = webView.getEngine();
        Controller controller = new Controller();
        JSObject win = (JSObject) webEngine.executeScript("window");
        win.setMember("app", controller);

        month.setOnAction(event -> {
            String loadFile = this.getClass().getResource("index.html").toString();
            webEngine.load(loadFile);
        });
    }
}

My index.html (uploaded by WebEngine):

<html>
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" type="text/css" href="style.css">
    </head>

    <body onload="readTextFile()">
        <div id="text">
        </div>
        <script type="text/javascript">
            function readTextFile() {
                var xhr, i, text, lines;
                xhr = new XMLHttpRequest();
                xhr.open('GET', app.getMonthIndex()+'.txt', true);
                xhr.send(null);
                xhr.onreadystatechange = function(){
                    text = xhr.responseText;
                    lines = text.split("\n");
                    var allText = "";
                    for(i = 0; i < lines.length; i++){
                        allText += lines[i]+"<br>";
                    }
                    document.getElementById("text").innerHTML = allText;
                }
            }
        </script>
    </body>
</html>

Solution

  • You’re creating a new instance of the Controller, which has no connection at all to the UI, and passing it to the web engine:

        Controller controller = new Controller();
         JSObject win = (JSObject) webEngine.executeScript("window");
        win.setMember("app", controller);
    

    Instead, just pass the current instance:

        // Controller controller = new Controller();
        JSObject win = (JSObject) webEngine.executeScript("window");
        win.setMember("app", this);