Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FXML: Binding to controller

Is it possible to bind in FXML just like in xaml to the controller to a class varibale. What I am doing is:

FXML

<ComboBox fx:id="searchField" 
                    HBox.hgrow="ALWAYS" editable="true" />
<GridPane hgap="5" vgap="5">
    <Label text="Nom" />
    <Label text="$selecteClient.name"
        GridPane.columnIndex="1" />

    <Label GridPane.rowIndex="1" text="tél" />
    <Label text="$electedClient.phoneNumber"
        GridPane.rowIndex="1" GridPane.columnIndex="1" />
<GridPane/>

Controler:

private final List<Client> clients = FXCollections.observableArrayList(ImportingDataService.importClients());
@FXML
private Client selectedClient;

@FXML
private ComboBox<Client> searchField;

@Override
public void initialize(URL location, ResourceBundle resources) {
    // Set appDtat client id so it refreshes when client is changed
    this.appState.clientViewClientIDProperty().addListener((obs, oldValue, newValue) -> {
        selectedClient = ImportingDataService.importClient(newValue.longValue());

    });

    // Set up combo box
    setUpComboBox();

}
private void setUpComboBox() {
    searchField.getItems().addAll(clients);
    UtilService.autoCompleteComboBoxPlus(searchField, (typedText, client) -> client.getName().contains(typedText));

    // Handle selecting clients
    searchField.getSelectionModel().selectedItemProperty().addListener((obs, oldValue, newValue) -> {
        selectedClient = ImportingDataService.importClient(newValue.getId());
    });
}

My Client class is a class that has the String fields name and phoneNumber. and the ImportingDataService.importClient is for importing data from database, they work just fine (I placed breakpoints and checked that). The problem is that I don't know why the client Labels do not update when I change the selection of the ComboBox, while the selectedClient does change. What am I doing wrong?

like image 533
Ayoub.A Avatar asked Apr 16 '26 04:04

Ayoub.A


1 Answers

There are multiple reasons for this:

  1. A simple field is not observable.
  2. You do not include controller in the expression binding.
  3. There is a typo here $selecteClient.name and here $electedClient.phoneNumber.
  4. The whole expression needs to be wrapped inside {} to be bound, not just set.

You could e.g. fix it like this:

Controller

private final ObjectProperty<Client> selectedClient = new SimpleObjectProperty<>(initialClient);

public final Client getSelectedClient() {
    return this.selectedClient.get();
}

public final void setSelectedClient(Client value) {
    this.selectedClient.set(value);
}

public final ObjectProperty<Client> selectedClientProperty() {
    return this.selectedClient;
}

...

// selectedClient = ImportingDataService.importClient(newValue.getId());
setSelectedClient(ImportingDataService.importClient(newValue.getId()));

fxml

<ComboBox fx:id="searchField" 
                    HBox.hgrow="ALWAYS" editable="true" />
<GridPane hgap="5" vgap="5">
    <Label text="Nom" />
    <Label text="${controller.selectedClient.name}"
        GridPane.columnIndex="1" />

    <Label GridPane.rowIndex="1" text="tél" />
    <Label text="${controller.selectedClient.phoneNumber}"
        GridPane.rowIndex="1" GridPane.columnIndex="1" />
<GridPane/>

Client

public String getName() {
    return name;
}

public String getPhoneNumber() {
    return phoneNumber;
}

(or something similar)

like image 89
fabian Avatar answered Apr 19 '26 06:04

fabian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!