Spring Boot and Vaadin : Filtering rows in Vaadin Grid
Adding a text field for filtering:
Start by adding a text field above the grid. Remember, MainView is a VerticalLayout, so you need to add the text field before the grid.
MainView.java
public class MainView extends VerticalLayout {
private ContactService contactService;
private Grid<Contact> grid = new Grid<>(Contact.class);
private TextField filterText = new TextField(); ①
public MainView(ContactService contactService) {
this.contactService = contactService;
addClassName("list-view");
setSizeFull();
configureFilter(); ②
configureGrid();
add(filterText, grid); ③
updateList();
}
private void configureFilter() {
filterText.setPlaceholder("Filter by name..."); ④
filterText.setClearButtonVisible(true); ⑤
filterText.setValueChangeMode(ValueChangeMode.LAZY); ⑥
filterText.addValueChangeListener(e -> updateList()); ⑦
}
// Grid configuration omitted
}
① Creates a field for the TextField.
② Calls the configureFilter() method to configure what the filter should do.
③ Updates the add() method call to add both filterText and grid.
④ Sets placeholder text so users know what to type in the field.
⑤ Sets the clear button to visible so users can easily clear the filter.
⑥ Sets the value change mode to LAZY so the text field will notify you of changes automatically after a short timeout in typing.
⑦ Calls the updateList method whenever the value changes. We’ll update the logic to filter the content shortly.
Implementing filtering in the back end We could implement the filtering in two ways:
1. Keep a copy of the contacts list in the view and filter it using Java streams.
2. Defer the filtering to the back end (database).
It’s a best practice to avoid keeping references to lists of objects in Vaadin views, as this can lead to excessive memory usage.
We’ll add filtering support to the back end:
1. Amend ContactService as follows:
ContactService.java
public class ContactService {
private static final Logger LOGGER = Logger.getLogger(ContactService.class
.getName());
private ContactRepository contactRepository;
private CompanyRepository companyRepository;
public ContactService(ContactRepository contactRepository,
CompanyRepository
companyRepository) {
this.contactRepository = contactRepository;
this.companyRepository = companyRepository;
}
public List<Contact> findAll() {
return contactRepository.findAll();
}
public List<Contact> findAll(String stringFilter) { ①
if (stringFilter == null || stringFilter.isEmpty()) { ②
return contactRepository.findAll();
} else {
return contactRepository.search(stringFilter); ③
}
}
// remaining methods omitted
}
① Adds a new findAll method that takes a filter text as a parameter.
② If the filter text is not empty, search the database for that text.
③ Otherwise, return all contacts
2. Add the search method to the contacts repository.
ContactRepository.java
public interface ContactRepository extends JpaRepository<Contact, Long> {
@Query("select c from Contact c " +
"where lower(c.firstName) like lower(concat('%', :searchTerm, '%')) " +
"or lower(c.lastName) like lower(concat('%', :searchTerm, '%'))") ①
List<Contact> search(@Param("searchTerm") String searchTerm); ②
}
① Uses the @Query annotation to define a custom query. In this case, it checks if the string matches the first or the last name, and ignores the case. The query uses Java Persistence Query Language (JPQL) which is an SQL-like language for querying JPA managed databases.
② Selects the Spring Framework import for @Param.
3. Update the way MainView updates the contacts. This is the method that is called every time the filter text field changes.
MainView.java
private void updateList() {
grid.setItems(contactService.findAll(filterText.getValue()));
}
4. Build the application and try out the filtering. You should be able to filter the contacts by entering a term in the text field.
So far, we’ve created an application that shows and filters contacts that are stored in a database. Next, we’ll add a form to add, remove, and edit contacts.
Start by adding a text field above the grid. Remember, MainView is a VerticalLayout, so you need to add the text field before the grid.
MainView.java
public class MainView extends VerticalLayout {
private ContactService contactService;
private Grid<Contact> grid = new Grid<>(Contact.class);
private TextField filterText = new TextField(); ①
public MainView(ContactService contactService) {
this.contactService = contactService;
addClassName("list-view");
setSizeFull();
configureFilter(); ②
configureGrid();
add(filterText, grid); ③
updateList();
}
private void configureFilter() {
filterText.setPlaceholder("Filter by name..."); ④
filterText.setClearButtonVisible(true); ⑤
filterText.setValueChangeMode(ValueChangeMode.LAZY); ⑥
filterText.addValueChangeListener(e -> updateList()); ⑦
}
// Grid configuration omitted
}
① Creates a field for the TextField.
② Calls the configureFilter() method to configure what the filter should do.
③ Updates the add() method call to add both filterText and grid.
④ Sets placeholder text so users know what to type in the field.
⑤ Sets the clear button to visible so users can easily clear the filter.
⑥ Sets the value change mode to LAZY so the text field will notify you of changes automatically after a short timeout in typing.
⑦ Calls the updateList method whenever the value changes. We’ll update the logic to filter the content shortly.
Implementing filtering in the back end We could implement the filtering in two ways:
1. Keep a copy of the contacts list in the view and filter it using Java streams.
2. Defer the filtering to the back end (database).
It’s a best practice to avoid keeping references to lists of objects in Vaadin views, as this can lead to excessive memory usage.
We’ll add filtering support to the back end:
1. Amend ContactService as follows:
ContactService.java
public class ContactService {
private static final Logger LOGGER = Logger.getLogger(ContactService.class
.getName());
private ContactRepository contactRepository;
private CompanyRepository companyRepository;
public ContactService(ContactRepository contactRepository,
CompanyRepository
companyRepository) {
this.contactRepository = contactRepository;
this.companyRepository = companyRepository;
}
public List<Contact> findAll() {
return contactRepository.findAll();
}
public List<Contact> findAll(String stringFilter) { ①
if (stringFilter == null || stringFilter.isEmpty()) { ②
return contactRepository.findAll();
} else {
return contactRepository.search(stringFilter); ③
}
}
// remaining methods omitted
}
① Adds a new findAll method that takes a filter text as a parameter.
② If the filter text is not empty, search the database for that text.
③ Otherwise, return all contacts
2. Add the search method to the contacts repository.
ContactRepository.java
public interface ContactRepository extends JpaRepository<Contact, Long> {
@Query("select c from Contact c " +
"where lower(c.firstName) like lower(concat('%', :searchTerm, '%')) " +
"or lower(c.lastName) like lower(concat('%', :searchTerm, '%'))") ①
List<Contact> search(@Param("searchTerm") String searchTerm); ②
}
① Uses the @Query annotation to define a custom query. In this case, it checks if the string matches the first or the last name, and ignores the case. The query uses Java Persistence Query Language (JPQL) which is an SQL-like language for querying JPA managed databases.
② Selects the Spring Framework import for @Param.
3. Update the way MainView updates the contacts. This is the method that is called every time the filter text field changes.
MainView.java
private void updateList() {
grid.setItems(contactService.findAll(filterText.getValue()));
}
4. Build the application and try out the filtering. You should be able to filter the contacts by entering a term in the text field.
So far, we’ve created an application that shows and filters contacts that are stored in a database. Next, we’ll add a form to add, remove, and edit contacts.
Comments
Post a Comment