2 Replies Latest reply: Jan 17, 2013 9:15 AM by James_D RSS

    TableView nested columns binding with nested objects

    928144
      Let's suppose i have an object like this
      class Person {
          SimpleStringProperty name;
          SimpleStringProperty surname;
          SimpleObjectProperty<Address> address;
      ...
      }
      class Address {
          SimpleStringProperty client;
          SimpleStringProperty address;
          SimpleIntegerProperty number;
      ...
      }
      is there a way to bind a TableView<Person> in order to have a column and nested column for the object Address ?
      /* First name column */
      TableColumn firstNameCol = new TableColumn("First Name");
      firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("name"));
      
      /* Last name column */
      TableColumn lastNameCol = new TableColumn("Last Name");
      lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("surname"));
      
      /* Address main column */
      TableColumn addressCol = new TableColumn("Address Informations");
      addressCol.setCellValueFactory(new PropertyValueFactory<Person, Address>("address"));
      /* Client nestedcolumn */
      TableColumn clientCol = new TableColumn("Client");
      clientCol.setCellValueFactory(new PropertyValueFactory<Address, String>("client"));
      /* Address nested column */
      TableColumn addrCol = new TableColumn("Address");
      addrCol .setCellValueFactory(new PropertyValueFactory<Address, String>("address"));
      /* Number nested column */
      TableColumn numberCol = new TableColumn("Number");
      numberCol .setCellValueFactory(new PropertyValueFactory<Address, Integer>("number"));
      addressCol.getColumns().addAll(clientCol, addrCol , numberCol );
      
      getColumns().addAll(firstNameCol, lastNameCol, addressCol);
      of course i tried this and doesn't work..
        • 1. Re: TableView nested columns binding with nested objects
          984080
          Hey,

          Looks a good question!
          Welh, even if I didn't try.. I suppose you could look in this direction:


          I would try to pass the hole object 'Address' to the different TableColumns 'client', 'address' and 'number'.
          clientCol.setCellValueFactory(new PropertyValueFactory<Person, Address>("address"));
          addrCol.setCellValueFactory(new PropertyValueFactory<Person, Address>("address"));
          numberCol.setCellValueFactory(new PropertyValueFactory<Person, Address>("address"));
          Then create your own CellFactories for every TableColumn.
          Link it this way.
          clientCol.setCellFactory(myCustomCellFactory);
          Your CellFactory should look like this:
          public class myCustomCellFactory extends TableCell<Object, Address> {
              //constructor
              public myCustomCellFactory() {
              }
          
              //methods
              @Override
              public void startEdit() {
              }
          
              @Override
              public void updateItem(Address oAddress, boolean empty) {
                  super.updateItem(item, empty);
          
                  if (!isEmpty()) {
                          setText(oAddress.getClient());
                  }
              }
          }
          I'm not sure this example works, I've coded it here..
          Hope it helps..

          Edited by: FXdude on 17-jan-2013 6:55
          • 2. Re: TableView nested columns binding with nested objects
            James_D
            You can do
            clientCol.setCellValueFactory(new Callback<CellDataFeatures<Person, String>, ObservableValue<String>>() {
                 public ObservableValue<String> call(CellDataFeatures<Person, String> p) {
                     return p.getValue().getAddress().clientProperty();
                 }
              });
            I think when Java8 is out this reduces to
            clientCol.setCellValueFactory((p)->p.getValue().getAddress().clientProperty());
            but until then you have to use the verbose version above.