3

I have custom component with few labels and few textFields. I need to instantiate it 3 times, but each version must have all labels prefixed with different String.

Fragment of my component fxml:

<Label text="inclusions type:"/>
<Label text="inclusions size:" GridPane.rowIndex="1"/>
<Label text="inclusions number:" GridPane.rowIndex="2"/>

I would like to achieve some kind of code placeholder like:

<Label text="$variable inclusions type:"/>
<Label text="$variable size:" GridPane.rowIndex="1"/>
<Label text="$variable number:" GridPane.rowIndex="2"/>

I try to avoid injecting all labels one by one, as I know there is no possibility to inject all labels at once to controller like ex. Collection<Label> allLabels;

Question: How to pass String from controller code to fxml view, avoiding duplication and unnecessary work?

jewelsea
  • 150,031
  • 14
  • 366
  • 406
Michał Mielec
  • 1,582
  • 1
  • 14
  • 38
  • 1
    If you want to add components dynamically you should instantiate and add them to scene in java code! Fxml is for defining static components manually. There is no point in having dynamic components in a Fxml file. – Omid Dec 02 '16 at 21:39
  • I understand, but having .fxml files and "Swing style" code together is not good for me. But I am little pedantic :D – Michał Mielec Dec 02 '16 at 21:44
  • 1
    I think I misunderstood. If you want to inject part of label's text and not many labels with some variable text, it makes sense! – Omid Dec 02 '16 at 21:52

1 Answers1

4

You can use a binding expression in your FXML to grab variable values out of the FXML namespace.

In the following example, we successfully inject the name "Foobar".

foobar

inclusions.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>

<VBox spacing="10" xmlns:fx="http://javafx.com/fxml">
  <Label text="${name + ' inclusions type'}"/>
  <Label text="${name + ' inclusions size'}"/>
  <Label text="${name + ' inclusions number'}"/>
</VBox>

NamespaceAware.java

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class NamespaceAware extends Application {
    @Override
    public void start(final Stage stage) throws Exception {
        FXMLLoader loader = new FXMLLoader();
        loader.getNamespace().put("name", "Foobar");
        loader.setLocation(getClass().getResource("inclusions.fxml"));
        Pane content = loader.load();

        content.setPadding(new Insets(10));

        stage.setScene(new Scene(content));
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
jewelsea
  • 150,031
  • 14
  • 366
  • 406
  • I tried this, but I did not figure out single quotes and FxmlLoader threw Exception to me. Thanks!!! – Michał Mielec Dec 02 '16 at 21:47
  • It seems Scene builders (both from Oracle and Gluon) does not support concatenation. – Michał Mielec Dec 02 '16 at 22:52
  • 1
    Yeah, that's something you would have to take up with Gluon. I don't know how you would do that. Bizarrely, their support page links back to StackOverflow and I don't see an issue tracker link in their support pages. Maybe if you just tag the question Gluon or something they might investigate it. Gluon also offer commercial support and have a link on their page to request that, so that is a possible route. Intellij idea inspections don't correctly parse the expression either. So feature request could also be filed against Intellij. – jewelsea Dec 02 '16 at 23:00