Search code examples
javafxtableviewfxmltablecolumn

How to access parent value from nested TableColumn


I have a table (TableView) in which there is frequent repetition of a group of columns (for example, name and address). I group these columns as sub-columns of a common column

<TableColumn text="Получател">
    <columns>
        <TableColumn text="ЕИК"/>
        <TableColumn text="ЗДДС №"/>
        <TableColumn text="Име"/>
        <TableColumn text="Адрес"/>
        <TableColumn text="Материално отговорно лице"/>
        <TableColumn text="Получател"/>
    </columns>
</TableColumn>

I export this group of columns to user control

<fx:root type="com.example.CompanyTableColumn" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml"
         text="${controller.name}">

    <columns>
        <TableColumn fx:id="eikColumn" text="ЕИК"/>
        <TableColumn fx:id="vatColumn" text="ЗДДС №"/>
        <TableColumn fx:id="nameColumn" text="Име"/>
        <TableColumn fx:id="addressColumn" text="Адрес"/>
        <TableColumn text="Материално отговорно лице"/>
    </columns>

</fx:root>
public class CompanyTableColumn extends TableColumn<Invoice, Company> {

    @FXML
    private TableColumn<Invoice, String> eikColumn;

    @FXML
    private TableColumn<Invoice, String> vatColumn;

    @FXML
    private TableColumn<Invoice, String> nameColumn;

    @FXML
    private TableColumn<Invoice, String> addressColumn;

    private StringProperty name = new SimpleStringProperty();

    public CompanyTableColumn() {
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(getClass().getResource("/com/example/table_column_company.fxml"));
            loader.setRoot(this);
            loader.setController(this);

            loader.load();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    @FXML
    private void initialize() {
        
    }

    public String getName() {
        return name.get();
    }

    public StringProperty nameProperty() {
        return name;
    }

    public void setName(String name) {
        this.name.set(name);
    }
}

By initializing user control as follows

<TableView fx:id="tableView">
    <columns>
        <CompanyTableColumn fx:id="supplierColumn" name="Доставчик"/>
        <CompanyTableColumn fx:id="receiverColumn" name="Получател"/>
    <columns>
</TableView>
supplierColumn.setCellValueFactory(cdf -> new SimpleObjectProperty<>(cdf.getValue().getSupplier()));
receiverColumn.setCellValueFactory(cdf -> new SimpleObjectProperty<>(cdf.getValue().getReceiver()));

And here comes my problem. In the example, the two controls must visualize data from different instances of the Company model. I submit the various instances by creating a CellValueFactory but I don't see how I can access the specific value in CompanyTableColumn so I can use it in the factories that create the values of the nested columns.

edit

As usual, the solution is found shortly after the question is asked:

@FXML
private void initialize() {
    eikColumn.setCellValueFactory(cdf -> new SimpleStringProperty(getCellObservableValue(cdf.getValue()).getValue().getEik()));
    vatColumn.setCellValueFactory(cdf -> new SimpleStringProperty(getCellObservableValue(cdf.getValue()).getValue().getVat()));
    nameColumn.setCellValueFactory(cdf -> new SimpleStringProperty(getCellObservableValue(cdf.getValue()).getValue().getName()));
    addressColumn.setCellValueFactory(cdf -> new SimpleStringProperty(getCellObservableValue(cdf.getValue()).getValue().getAddress()));
}

Solution

  • The solution I found consisted of calling TableColumn::getCellObservableValue using the value corresponding to the corresponding row in the table as a parameter (returned by the CellDataFeatures object used in the callback function to generate a value)

    public class CompanyTableColumn extends TableColumn<Invoice, Company> {
    
        @FXML
        private TableColumn<Invoice, String> eikColumn;
    
        @FXML
        private TableColumn<Invoice, String> vatColumn;
    
        @FXML
        private TableColumn<Invoice, String> nameColumn;
    
        @FXML
        private TableColumn<Invoice, String> addressColumn;
    
        private StringProperty name = new SimpleStringProperty();
    
        public CompanyTableColumn() {
            try {
                FXMLLoader loader = new FXMLLoader();
                loader.setLocation(getClass().getResource("/com/example/table_column_company.fxml"));
                loader.setRoot(this);
                loader.setController(this);
    
                loader.load();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        @FXML
        private void initialize() {
            eikColumn.setCellValueFactory(cdf -> new SimpleStringProperty(getCellObservableValue(cdf.getValue()).getValue().getEik()));
            vatColumn.setCellValueFactory(cdf -> new SimpleStringProperty(getCellObservableValue(cdf.getValue()).getValue().getVat()));
            nameColumn.setCellValueFactory(cdf -> new SimpleStringProperty(getCellObservableValue(cdf.getValue()).getValue().getName()));
            addressColumn.setCellValueFactory(cdf -> new SimpleStringProperty(getCellObservableValue(cdf.getValue()).getValue().getAddress()));
        }
    
        public String getName() {
            return name.get();
        }
    
        public StringProperty nameProperty() {
            return name;
        }
    
        public void setName(String name) {
            this.name.set(name);
        }
    }