title: JavaFX connected comboboxes
body: <p>I could really use some help.</p>
  
  <p>I am  creating application that has two connected comboboxes in a way that if i select productCode in first in second one should be selected productName.</p>
  
  <p>Both combobox textfields are filtrable for search purposes.</p>
  
  <p>I have set setCellFactories like this (for purpose of dropdown list rendering).</p>
  
  <pre><code>    cbSifra.setCellFactory((comboBox) -&gt; new ListCell&lt;Product&gt;() {
          @Override
          protected void updateItem(Product product, boolean empty) {
              super.updateItem(product, empty);
  
              if (product == null || empty) {
                  setText(null);
              } else {
                  setText(product.getProductCode());
              }
          }
      });
  
  cbNaziv.setCellFactory((comboBox) -&gt; new ListCell&lt;Product&gt;() {
          @Override
          protected void updateItem(Product product, boolean empty) {
              super.updateItem(product, empty);
  
              if (product == null || empty) {
                  setText(null);
              } else {
                  setText(product.getProductName());
              }
          }
      });
  </code></pre>
  
  <p>Both comboboxes implement converters to show data into combobox when selected.</p>
  
  <pre><code>cbNaziv.setConverter(new StringConverter&lt;Product&gt;() {
          @Override
          public String toString(Product product) {
              if (product == null) {
                  return null;
              } else {
                  return product.productNameProperty().get();
              }
          }
  
          @Override
          public Product fromString(String productString)
          {
              return cbNaziv.getItems().stream().filter(item-&gt;productString.equals(item.getProductName())).findFirst().orElse(null);
  
          }
      });
  
  
      cbSifra.setConverter(new StringConverter&lt;Product&gt;() {
          @Override
          public String toString(Product product) {
              if (product == null) {
                  return null;
              } else {
                  return product.productCodeProperty().get();
              }
          }
  
          @Override
          public Product fromString(String productString)
          {
              return cbSifra.getItems().stream().filter(item -&gt;productString.equals(item.getProductCode())).findAny().orElse(null);
          }
      });
  </code></pre>
  
  <p>Filtering of dropdown list is done using Listener on textProperty() like this:</p>
  
  <pre><code>cbNaziv.getEditor().textProperty().addListener((obs, oldValue, newValue) -&gt; {
  
  
                  cbNaziv.show();
  
                  final TextField editor = cbNaziv.getEditor();
                  final Product selected = cbNaziv.getSelectionModel().getSelectedItem();
  
          /*
          This needs run on the GUI thread to avoid the error described
          here: https://bugs.openjdk.java.net/browse/JDK-8081700.
          */
  
                  Platform.runLater(() -&gt; {
  
              /*
              If the no item in the list is selected or the selected item
              isn't equal to the current input, we refilter the list.
              */
                      if (selected == null || !selected.equals(editor.getText())) {
                          filteredProductList.setPredicate(item -&gt; {
                              // We return true for any items that contains the
                              // same letters as the input. We use toUpperCase to
                              // avoid case sensitivity.
  
                              if (item.getProductName().toUpperCase().contains(newValue.toUpperCase())) {
                                  return true;
                              } else {
                                  return false;
                              }
                          });
                      }
                  });
              });
  
  
  
              cbSifra.getEditor().textProperty().addListener((obs, oldValue, newValue) -&gt; {
  
  
                  cbSifra.show(); // Is used to open dropdown list as i start typing
  
                  final TextField editor = cbSifra.getEditor();
                  final Product selected = cbSifra.getSelectionModel().getSelectedItem();
  
          /*
          This needs run on the GUI thread to avoid the error described
          here: https://bugs.openjdk.java.net/browse/JDK-8081700.
          */
  
                  Platform.runLater(() -&gt; {
  
              /*
              If the no item in the list is selected or the selected item
              isn't equal to the current input, we refilter the list.
              */
  
                      if (selected == null || !selected.equals(editor.getText())) {
  
                          filteredProductList.setPredicate(item -&gt; {
                              // We return true for any items that contains the
                              // same letters as the input. We use toUpperCase to
                              // avoid case sensitivity.
  
                              if (item.getProductCode().toUpperCase().contains(newValue.toUpperCase())) {
                                  return true;
                              } else {
                                  return false;
                              }
  
                          });
                      }
                  });
              });
  </code></pre>
  
  <p>I have valueProperty Listeners to check if value is selected and to fill some textFields to their values or set them to null.</p>
  
  <pre><code>cbSifra.valueProperty().addListener(new ChangeListener&lt;Product&gt;() {
              @Override
              public void changed(ObservableValue&lt;? extends Product&gt; observable, Product oldValue, Product newValue) {
  
                  if (cbSifra.getValue() == null || cbSifra.getValue().getProductName().isEmpty())
                  {
                      cbNaziv.getSelectionModel().clearSelection();
                      tfMpCijena.setText(null);
                      tfPopust.setText(null);
  
                  } else {
  
  
                      cbNaziv.setValue(cbSifra.getValue());
                      cbSifra.setValue(cbNaziv.getValue());
                      cbNaziv.hide();
                      tfMpCijena.setText(cbSifra.getValue().getProductRetailPrice().toString());
                      tfPopust.setText("0");
                  }
  
              }
          });
  
  
  
          cbNaziv.valueProperty().addListener(new ChangeListener&lt;Product&gt;() {
              @Override
              public void changed(ObservableValue&lt;? extends Product&gt; observable, Product oldValue, Product newValue) {
  
                  if (cbNaziv.getValue() == null || cbNaziv.getValue().getProductName().isEmpty())
                  {
                      cbSifra.getSelectionModel().clearSelection();
                      tfMpCijena.setText(null);
                      tfPopust.setText(null);
  
                  } else {
  
                      cbSifra.setValue(cbNaziv.getValue());
                      cbSifra.hide();
                      tfMpCijena.setText(cbNaziv.getValue().getProductRetailPrice().toString());
                      tfPopust.setText("0");
                  }
  
              }
          });
  </code></pre>
  
  <p>The problems are :</p>
  
  <ul>
  <li><p>when i start typing something into any combobox it filters ok and
  when i   select item from dropdown list it fills second combobox but
  first combobox      editor gets focus again and displays dropdown
  again</p></li>
  <li><p>when i delete entry from combobox it deletes ok but the other
  combobox value remains (it isnt deleted)</p></li>
  </ul>
  
  <p>If you can help me i would really appreciate it.
  Thanks in advance.</p>