0

I am using Vaadin 14 (14.1.17) and data provider with multi-select. When I hit select all button, the rows aren't selected at UI but they are selected at backend(grid.getSelectedItems() works). In addition, when I select one row and then hit select all button, grid.getSelectedItems holds the previous value, so it gives grids.size() + 1 instead of unselecting the previous value that was selected before.

My data provider and bean are like this:

@Entity
@EqualsAndHashCode
@Table(name = "forms", schema = "click", catalog = "")
public class FormEntity {

    private long id;
    private String userId;
    private String requestorType;
    private String confirmationPhone;
    private Timestamp submittedDate;
    private int status;
    private Timestamp approvedDate;
    private String comments;
    private String organization;
    private PatientEntity patientEntity;


    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    @Basic
    @Column(name = "user_id", nullable = true, length = 70)
    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    @Basic
    @Column(name = "requestor_type", nullable = false, length = 50)
    public String getRequestorType() {
        return requestorType;
    }

    public void setRequestorType(String requestorType) {
        this.requestorType = requestorType;
    }

    @Basic
    @Column(name = "confirmation_phone", nullable = true, length = 50)
    public String getConfirmationPhone() {
        return confirmationPhone;
    }

    public void setConfirmationPhone(String confirmationPhone) {
        this.confirmationPhone = confirmationPhone;
    }


    @Basic
    @Column(name = "submitted_date", nullable = false)
    public Timestamp getSubmittedDate() {
        return submittedDate;
    }

    public void setSubmittedDate(Timestamp submittedDate) {
        this.submittedDate = submittedDate;
    }

    @Basic
    @Column(name = "status", nullable = false, length = 11)
    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    @Basic
    @Column(name = "approved_date", nullable = false)
    public Timestamp getApprovedDate() {
        return approvedDate;
    }

    public void setApprovedDate(Timestamp approvedDate) {
        this.approvedDate = approvedDate;
    }

    @Basic
    @Column(name = "comments", nullable = true)
    public String getComments() {
        return comments;
    }

    public void setComments(String comments) {
        this.comments = comments;
    }

    @Basic
    @Column(name = "organization", nullable = true)
    public String getOrganization() {
        return organization;
    }

    public void setOrganization(String organization) {
        this.organization = organization;
    }

    @ManyToOne
    @JoinColumn(name = "patient_id", referencedColumnName = "id", nullable = false)
    public PatientEntity getPatientEntity() {
        return patientEntity;
    }

    public void setPatientEntity(PatientEntity patientEntity) {
        this.patientEntity = patientEntity;
    }
}


 private ConfigurableFilterDataProvider<FormEntity, Void, Map<String, Object>> getFilteringDataProvider(OrganizationDto organizationDto) {


        DataProvider<FormEntity, Map<String, Object>> dataProvider =
                DataProvider.fromFilteringCallbacks(
                        query -> {
                            Map.Entry<String, String> sortOrder = null;
                            List<QuerySortOrder> sortOrderList = query.getSortOrders();

                            if (!sortOrderList.isEmpty()) {
                                QuerySortOrder querySortOrder = sortOrderList.get(0);
                                sortOrder = new AbstractMap.SimpleEntry<>(querySortOrder.getSorted(),
                                        querySortOrder.getDirection().name());
                            }

                            Map<String, Object> filter = query.getFilter().orElse(null);

                            List<FormEntity> rv = null;
                            rv = registrationService.fetchForms(organizationDto.getIdentifier(), filter, query.getOffset(), query.getLimit(), sortOrder).getContent();
                            System.out.println("List size:" + rv.size());
                            return rv.stream();
                        },
                        query -> {
                            Map<String, Object> filter = query.getFilter().orElse(null);

                            long count = 0;
                            //The second callback finds out how many items there are in total in the datasource matching with current filters.
                            count = registrationService.fetchForms(organizationDto.getIdentifier(), filter, 0, 1, null).getTotalElements();
                            System.out.println("Count:" + count);

                            return (int) count;
                        }
                );

        return dataProvider.withConfigurableFilter();
    }
2
  • A bit more info would be needed for a good answer. This looks like bean identity issue. So you should reveal details how you have implemented the bean used as item, and have you overridden DataProvider#getId or not. There was also edge case bug in multiselection, that has been fixed in Vaadin 23.0 and 23.1, but not yet in Vaadin 14, see: github.com/vaadin/flow-components/pull/2947 Commented Jun 15, 2022 at 6:58
  • @TatuLund I have edited my answer by adding some code. I haven't overriden DataProvider#getId. I can try it. Commented Jun 16, 2022 at 7:34

1 Answer 1

2

You seem to use @EqualsAndHashCode of Lombok. By default it generates eqauals and hashcode that use all the properties of the entity. This does not work with Vaadin's data model, as it expects the beans to be invariant, i.e. changing value of properties like confirmationPhone should not affect the beans identity. You can solve this either 1. defining in Lomboks annotation that uses only the id or userId for the equals and hashcode. Or 2. Extend DataProvider and override getId method so that uses either one.

Example of Lombok use below

@Entity
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Table(name = "forms", schema = "click", catalog = "")
public class FormEntity {

    @EqualsAndHashCode.Include private long id;
    private String userId;
    private String requestorType;
    private String confirmationPhone;
    private Timestamp submittedDate;
    private int status;
    private Timestamp approvedDate;
    private String comments;
    private String organization;
    private PatientEntity patientEntity;
    ...
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, I tried the code that you have provided and it works! :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.