Skip to content

Commit a870985

Browse files
vursenclaude
authored andcommitted
fix: allow filtering out all values in spreadsheet filter (#9574)
In the spreadsheet filter popup, unchecking "Select All" had no effect, and when unchecking values one by one, the last one didn't do anything either. The selection looked empty, but no filtering happened, and after closing the popup everything was selected again, which was confusing. Unchecking now hides the rows and the deselected state persists. The PR also hides the "Select All" checkbox entirely when all of a column's values are already filtered out by other columns. Fixes #9549 🤖 Generated with Claude Code Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 30e8cc0 commit a870985

2 files changed

Lines changed: 145 additions & 106 deletions

File tree

  • vaadin-spreadsheet-flow-parent/vaadin-spreadsheet-flow/src

vaadin-spreadsheet-flow-parent/vaadin-spreadsheet-flow/src/main/java/com/vaadin/flow/component/spreadsheet/ItemFilter.java

Lines changed: 32 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import java.util.Comparator;
1515
import java.util.HashSet;
1616
import java.util.Iterator;
17-
import java.util.LinkedHashSet;
1817
import java.util.List;
1918
import java.util.Set;
2019

@@ -24,8 +23,6 @@
2423
import com.vaadin.flow.component.checkbox.CheckboxGroup;
2524
import com.vaadin.flow.component.checkbox.CheckboxGroupVariant;
2625
import com.vaadin.flow.component.html.Div;
27-
import com.vaadin.flow.component.spreadsheet.PopupButton.PopupCloseEvent;
28-
import com.vaadin.flow.component.spreadsheet.PopupButton.PopupCloseListener;
2926
import com.vaadin.flow.component.spreadsheet.PopupButton.PopupOpenEvent;
3027
import com.vaadin.flow.component.spreadsheet.PopupButton.PopupOpenListener;
3128
import com.vaadin.flow.data.provider.ListDataProvider;
@@ -48,9 +45,7 @@ public class ItemFilter extends Div implements SpreadsheetFilter {
4845
private ListDataProvider<String> filterOptionsProvider;
4946
private List<String> filterOptions = new ArrayList<>();
5047
private ArrayList<String> allCellValues;
51-
private Collection<String> latestFilteredValues;
5248
private PopupButton popupButton;
53-
private boolean firstUpdate = true;
5449
private boolean cancelValueChangeUpdate;
5550
private SpreadsheetFilterTable filterTable;
5651
private Set<Integer> filteredRows;
@@ -77,7 +72,6 @@ public ItemFilter(CellRangeAddress filterRange, Spreadsheet spreadsheet,
7772

7873
allCellValues = new ArrayList<>();
7974
filteredRows = new HashSet<>();
80-
latestFilteredValues = new LinkedHashSet<>();
8175
initComponents();
8276
updateOptions();
8377
}
@@ -103,43 +97,11 @@ protected void initLayouts() {
10397
}
10498

10599
/**
106-
* Initializes pop-up close listener for verifying that filter selections
107-
* match with what is currently shown.
100+
* Initializes the pop-up open listener that refreshes the filter options
101+
* whenever the pop-up is opened.
108102
*/
109103
protected void initPopupButtonListeners() {
110104

111-
popupButton.addPopupCloseListener(new PopupCloseListener() {
112-
113-
@Override
114-
public void onPopupClose(PopupCloseEvent event) {
115-
// need to check that the filter wasn't left a different state
116-
// than what is displayed, like in case when allItems and all
117-
// options were left unchecked.
118-
if (!allItems.getValue()) {
119-
Collection<String> currentValue = filterCheckbox.getValue();
120-
cancelValueChangeUpdate = true;
121-
if (currentValue.isEmpty()) {
122-
if (latestFilteredValues.isEmpty()
123-
|| latestFilteredValues
124-
.containsAll(allCellValues)) {
125-
allItems.setIndeterminate(false);
126-
allItems.setValue(true);
127-
filterCheckbox
128-
.setValue(new HashSet<>(allCellValues));
129-
} else {
130-
filterCheckbox.setValue(
131-
new HashSet<>(latestFilteredValues));
132-
}
133-
} else {
134-
if (currentValue.containsAll(allCellValues)) {
135-
allItems.setIndeterminate(false);
136-
allItems.setValue(true);
137-
}
138-
}
139-
cancelValueChangeUpdate = false;
140-
}
141-
}
142-
});
143105
popupButton.addPopupOpenListener(new PopupOpenListener() {
144106

145107
@Override
@@ -163,6 +125,7 @@ protected void initAllItemsCheckbox() {
163125
updateFilteredItems(allCellValues);
164126
} else {
165127
filterCheckbox.setValue(Collections.emptySet());
128+
updateFilteredItems(Collections.emptySet());
166129
}
167130
cancelValueChangeUpdate = false;
168131
}
@@ -178,31 +141,21 @@ protected void initOptions() {
178141
filterCheckbox.setItems(filterOptionsProvider);
179142
filterCheckbox.addThemeVariants(CheckboxGroupVariant.LUMO_VERTICAL);
180143
filterCheckbox.addValueChangeListener(event -> {
181-
if (firstUpdate) {
182-
firstUpdate = false;
183-
} else {
184-
if (!cancelValueChangeUpdate) {
185-
Collection<String> value = filterCheckbox.getValue();
186-
// value should not be updated when options are empty and
187-
// all
188-
// items is unchecked - just as in Excel
189-
if (!value.isEmpty()) {
190-
updateFilteredItems(value);
191-
cancelValueChangeUpdate = true;
192-
if (value.containsAll(allCellValues)) {
193-
allItems.setIndeterminate(false);
194-
if (!allItems.getValue()) {
195-
allItems.setValue(true);
196-
}
197-
} else {
198-
if (allItems.getValue()) {
199-
allItems.setValue(false);
200-
allItems.setIndeterminate(true);
201-
}
202-
}
203-
cancelValueChangeUpdate = false;
204-
}
144+
if (!cancelValueChangeUpdate) {
145+
Collection<String> value = filterCheckbox.getValue();
146+
updateFilteredItems(value);
147+
cancelValueChangeUpdate = true;
148+
if (value.containsAll(allCellValues)) {
149+
allItems.setIndeterminate(false);
150+
allItems.setValue(true);
151+
} else if (value.isEmpty()) {
152+
allItems.setIndeterminate(false);
153+
allItems.setValue(false);
154+
} else {
155+
allItems.setValue(false);
156+
allItems.setIndeterminate(true);
205157
}
158+
cancelValueChangeUpdate = false;
206159
}
207160
});
208161
}
@@ -239,15 +192,26 @@ public void updateOptions() {
239192
Collections.sort(filterOptions, byString);
240193
}
241194

195+
// Hide "Select All" when there are no values to control, i.e. all of
196+
// this column's values are hidden by other columns' filters.
197+
allItems.setVisible(!allCellValues.isEmpty());
198+
242199
Set<String> visibleValues = getVisibleValues();
243200
cancelValueChangeUpdate = true;
244-
allItems.setIndeterminate(!visibleValues.containsAll(allCellValues));
245-
allItems.setValue(visibleValues.containsAll(allCellValues));
246-
cancelValueChangeUpdate = false;
201+
if (visibleValues.containsAll(allCellValues)) {
202+
allItems.setIndeterminate(false);
203+
allItems.setValue(true);
204+
} else if (visibleValues.isEmpty()) {
205+
allItems.setIndeterminate(false);
206+
allItems.setValue(false);
207+
} else {
208+
allItems.setValue(false);
209+
allItems.setIndeterminate(true);
210+
}
247211
filterOptionsProvider = new ListDataProvider<>(filterOptions);
248212
filterCheckbox.setItems(filterOptionsProvider);
249-
firstUpdate = true;
250213
filterCheckbox.setValue(visibleValues);
214+
cancelValueChangeUpdate = false;
251215
}
252216

253217
/**
@@ -299,7 +263,6 @@ protected void updateFilteredItems(Collection<String> visibleValues) {
299263
filteredRows.add(r);
300264
}
301265
}
302-
latestFilteredValues = new ArrayList<>(visibleValues);
303266

304267
filterTable.onFiltersUpdated();
305268
}

0 commit comments

Comments
 (0)