Sunday, November 17, 2013

How to implement Filter/Search for TableView in JavaFX

Filter or Search fields for tables are nothing new. Most of us would have used a custom filter field for JTable in Swing. In this post I'm going to show you how to implement a basic filter for TableView in JavaFX. You can download the source of the example from here.


This filter field will look for each cell in a row and if it finds a match in any of the row, then it retains the row in the TableView else removes it. I have used a TextField as the Filter component (actually, I have used TextFields.createSearchField() from the ControlsFX project. But a simple TextField will work). The filtering logic goes inside the invalidation listener, that is added to the text property of the TextField. I think this is a more cleaner way of implementing the logic, as opposed to implementing the logic in the Key listener (as we do in Swing). Below is the snippet on the filtering logic.

 
  1. private void initFilter() {
  2. txtField = TextFields.createSearchField();
  3. txtField.setPromptText("Filter");
  4. txtField.textProperty().addListener(new InvalidationListener() {
  5. @Override
  6. public void invalidated(Observable o) {
  7. if(txtField.textProperty().get().isEmpty()) {
  8. table.setItems(data);
  9. return;
  10. }
  11. ObservableList<Employee> tableItems = FXCollections.observableArrayList();
  12. ObservableList<TableColumn<Employee, ?>> cols = table.getColumns();
  13. for(int i=0; i<data.size(); i++) {
  14. for(int j=0; j<cols.size(); j++) {
  15. TableColumn col = cols.get(j);
  16. String cellValue = col.getCellData(data.get(i)).toString();
  17. cellValue = cellValue.toLowerCase();
  18. if(cellValue.contains(txtField.textProperty().get().toLowerCase())) {
  19. tableItems.add(data.get(i));
  20. break;
  21. }
  22. }
  23. }
  24. table.setItems(tableItems);
  25. }
  26. });
  27. }
Every time the text property of the TextField is invalidated, the listener will check for matching items in the table content and set the table with items that only match the filter criteria. In the above snippet, the variable data holds the original list of items for the table. In Swing context you can think of it like a original table model. So when you filter, a new list is created to hold only the matching rows and this list is set as items to the TableView. 

The whole example is available as a maven project. Download to explore more. This is a very basic implementation. Some of the limitations of this filter is that it calls toString() to compare the contents. That would need some clean up. More features like filtering based on column index, highlighting the matching text in the table, showing some animation in case of really big list of data etc.. can be added to make this a perfect JavaFX control. 

Happy coding!!  

Table Filter Demo Example : https://drive.google.com/file/d/0B96EBDPI6nZZX2VpdThBa3RnOGc/view?usp=sharing