Skip to content

Commit c55b786

Browse files
mshabarovtanbt
authored andcommitted
fix!: Use data view filter and sorting only to that component (#366)
In-memory filtering and sorting are now stored directly in component, which gives an opportunity to change it through the data view API for a certain component separately from other components bound to the same data provider. Fixes: vaadin/flow#8655 (cherry picked from commit ed24e9b)
1 parent 0d3a30d commit c55b786

File tree

27 files changed

+888
-190
lines changed

27 files changed

+888
-190
lines changed

vaadin-checkbox-flow-parent/vaadin-checkbox-flow-integration-tests/src/main/java/com/vaadin/flow/component/checkbox/tests/CheckboxGroupListDataViewPage.java

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
*/
1616
package com.vaadin.flow.component.checkbox.tests;
1717

18-
import java.util.ArrayList;
19-
import java.util.Arrays;
2018
import java.util.concurrent.atomic.AtomicReference;
2119
import java.util.stream.Collectors;
2220

@@ -25,12 +23,15 @@
2523
import com.vaadin.flow.component.checkbox.dataview.CheckboxGroupListDataView;
2624
import com.vaadin.flow.component.html.Div;
2725
import com.vaadin.flow.component.html.Span;
26+
import com.vaadin.flow.data.provider.DataProvider;
27+
import com.vaadin.flow.data.provider.ListDataProvider;
2828
import com.vaadin.flow.router.Route;
2929

3030
@Route("vaadin-checkbox-group-list-data-view")
3131
public class CheckboxGroupListDataViewPage extends Div {
3232

3333
static final String CHECKBOX_GROUP = "checkbox-group-data-view";
34+
static final String OTHER_CHECKBOX_GROUP = "other-checkbox-group-data-view";
3435
static final String ITEMS_SIZE = "size-span-data-view";
3536
static final String ITEM_PRESENT = "item-present-span-data-view";
3637
static final String ALL_ITEMS = "all-items-span-data-view";
@@ -49,16 +50,23 @@ public class CheckboxGroupListDataViewPage extends Div {
4950
public CheckboxGroupListDataViewPage() {
5051
CheckboxGroup<CheckboxGroupDemoPage.Person> checkboxGroup =
5152
new CheckboxGroup<>();
53+
CheckboxGroup<CheckboxGroupDemoPage.Person> otherCheckBox = new CheckboxGroup<>();
54+
5255
CheckboxGroupDemoPage.Person john =
5356
new CheckboxGroupDemoPage.Person(1, "John");
5457
CheckboxGroupDemoPage.Person paul =
5558
new CheckboxGroupDemoPage.Person(2, "Paul");
5659
CheckboxGroupDemoPage.Person mike =
5760
new CheckboxGroupDemoPage.Person(3, "Mike");
61+
62+
final ListDataProvider<CheckboxGroupDemoPage.Person> personListDataProvider = DataProvider
63+
.ofItems(john, paul, mike);
64+
5865
CheckboxGroupListDataView<CheckboxGroupDemoPage.Person> dataView =
59-
checkboxGroup.setItems(new ArrayList<>(Arrays.asList(
60-
john, paul, mike)
61-
));
66+
checkboxGroup.setItems(personListDataProvider);
67+
68+
otherCheckBox.setItems(personListDataProvider);
69+
6270
Span sizeSpan = new Span(String.valueOf(dataView.getItemCount()));
6371
Span containsItemSpan = new Span(String.valueOf(
6472
dataView.contains(john)));
@@ -104,15 +112,16 @@ public CheckboxGroupListDataViewPage() {
104112
Button updateName = new Button("Update first name",
105113
event -> {
106114
CheckboxGroupDemoPage.Person updatedPerson =
107-
dataView.getItem(3);
115+
dataView.getItem(0);
108116
updatedPerson.setName("Jack");
109117
dataView.refreshItem(updatedPerson);
110118
});
111119
Button deletePerson = new Button("Delete person",
112120
event -> dataView.removeItem(
113-
new CheckboxGroupDemoPage.Person(4, null)));
121+
new CheckboxGroupDemoPage.Person(1, null)));
114122

115123
checkboxGroup.setId(CHECKBOX_GROUP);
124+
otherCheckBox.setId(OTHER_CHECKBOX_GROUP);
116125
sizeSpan.setId(ITEMS_SIZE);
117126
containsItemSpan.setId(ITEM_PRESENT);
118127
allItemsSpan.setId(ALL_ITEMS);
@@ -131,6 +140,6 @@ public CheckboxGroupListDataViewPage() {
131140
add(checkboxGroup, sizeSpan, containsItemSpan, allItemsSpan,
132141
itemOnIndexSpan, currentItemSpan, hasNextItemSpan,
133142
hasPrevItemSpan, filterButton, sortButton, nextItemButton,
134-
prevItemButton, addNew, updateName, deletePerson);
143+
prevItemButton, addNew, updateName, deletePerson, otherCheckBox);
135144
}
136145
}

vaadin-checkbox-flow-parent/vaadin-checkbox-flow-integration-tests/src/test/java/com/vaadin/flow/component/checkbox/tests/CheckboxGroupListDataViewIT.java

Lines changed: 92 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,39 +18,51 @@
1818
import java.util.List;
1919
import java.util.stream.Collectors;
2020

21-
import com.vaadin.tests.AbstractComponentIT;
2221
import com.vaadin.flow.testutil.TestPath;
2322
import com.vaadin.testbench.TestBenchElement;
23+
import com.vaadin.tests.AbstractComponentIT;
2424
import org.junit.Assert;
25+
import org.junit.Before;
2526
import org.junit.Test;
2627
import org.openqa.selenium.By;
2728

2829
@TestPath("vaadin-checkbox-group-list-data-view")
2930
public class CheckboxGroupListDataViewIT extends AbstractComponentIT {
3031

31-
@Test
32-
public void checkboxGroupListDataView_dataViewApiRequested_dataAvailable() {
32+
private TestBenchElement checkboxGroup;
33+
private TestBenchElement otherCheckboxGroup;
34+
35+
@Before
36+
public void init() {
3337
open();
3438

35-
TestBenchElement checkboxGroup = $("vaadin-checkbox-group")
39+
checkboxGroup = $("vaadin-checkbox-group")
3640
.id(CheckboxGroupListDataViewPage.CHECKBOX_GROUP);
3741

38-
List<TestBenchElement> checkboxes =
39-
checkboxGroup.$("vaadin-checkbox").all();
42+
otherCheckboxGroup = $("vaadin-checkbox-group")
43+
.id(CheckboxGroupListDataViewPage.OTHER_CHECKBOX_GROUP);
44+
}
45+
46+
@Test
47+
public void getItems_showsCheckboxContent() {
48+
List<TestBenchElement> checkboxes = checkboxGroup.$("vaadin-checkbox")
49+
.all();
4050

4151
// Checkbox items size
4252
Assert.assertEquals("Unexpected checkbox count", 3, checkboxes.size());
4353

4454
// Data set size
45-
Assert.assertEquals("Unexpected item count", "3",
46-
$("span").id(CheckboxGroupListDataViewPage.ITEMS_SIZE)
47-
.getText());
55+
Assert.assertEquals("Unexpected item count", "3", $("span")
56+
.id(CheckboxGroupListDataViewPage.ITEMS_SIZE).getText());
4857

4958
// Data set content
5059
Assert.assertEquals("Unexpected checkbox labels", "John,Paul,Mike",
5160
$("span").id(CheckboxGroupListDataViewPage.ALL_ITEMS)
5261
.getText());
62+
}
5363

64+
@Test
65+
public void navigateBetweenItems_showCorrectItems() {
5466
// Item present
5567
Assert.assertEquals("Person 'John' is expected to be present", "true",
5668
$("span").id(CheckboxGroupListDataViewPage.ITEM_PRESENT)
@@ -62,60 +74,108 @@ public void checkboxGroupListDataView_dataViewApiRequested_dataAvailable() {
6274
.getText());
6375

6476
// Has next item
65-
Assert.assertEquals("Next item is expected", "true",
66-
$("span").id(CheckboxGroupListDataViewPage.HAS_NEXT_ITEM)
67-
.getText());
77+
Assert.assertEquals("Next item is expected", "true", $("span")
78+
.id(CheckboxGroupListDataViewPage.HAS_NEXT_ITEM).getText());
6879

6980
// Has previous item
70-
Assert.assertEquals("Previous item is expected", "true",
71-
$("span").id(CheckboxGroupListDataViewPage.HAS_PREVIOUS_ITEM)
72-
.getText());
81+
Assert.assertEquals("Previous item is expected", "true", $("span")
82+
.id(CheckboxGroupListDataViewPage.HAS_PREVIOUS_ITEM).getText());
7383

7484
findElement(By.id(CheckboxGroupListDataViewPage.NEXT_ITEM)).click();
7585

7686
// Next item
77-
Assert.assertEquals("Unexpected next item", "Mike",
78-
$("span").id(CheckboxGroupListDataViewPage.CURRENT_ITEM)
79-
.getText());
87+
Assert.assertEquals("Unexpected next item", "Mike", $("span")
88+
.id(CheckboxGroupListDataViewPage.CURRENT_ITEM).getText());
8089

8190
findElement(By.id(CheckboxGroupListDataViewPage.PREVIOUS_ITEM)).click();
8291

8392
// Previous item
84-
Assert.assertEquals("Unexpected previous item", "Paul",
85-
$("span").id(CheckboxGroupListDataViewPage.CURRENT_ITEM)
86-
.getText());
93+
Assert.assertEquals("Unexpected previous item", "Paul", $("span")
94+
.id(CheckboxGroupListDataViewPage.CURRENT_ITEM).getText());
95+
}
8796

88-
// Add item
97+
@Test
98+
public void addItem_itemAddedAndShownInBothComponents() {
8999
findElement(By.id(CheckboxGroupListDataViewPage.ADD_ITEM)).click();
90-
Assert.assertEquals("Wrong name for added person",
91-
"Peter",
100+
101+
Assert.assertEquals(
102+
"Unexpected item count after adding a new item in first "
103+
+ "CheckboxGroup",
104+
4, checkboxGroup.$("vaadin-checkbox").all().size());
105+
106+
Assert.assertEquals(
107+
"Wrong name for added person in first CheckboxGroup", "Peter",
92108
checkboxGroup.$("vaadin-checkbox").all().get(3).getText());
93109

94-
// Update item
110+
Assert.assertEquals(
111+
"Unexpected item count after adding a new item in"
112+
+ " second CheckboxGroup",
113+
4, checkboxGroup.$("vaadin-checkbox").all().size());
114+
115+
Assert.assertEquals(
116+
"Wrong name for added person in second " + "CheckboxGroup",
117+
"Peter",
118+
otherCheckboxGroup.$("vaadin-checkbox").all().get(3).getText());
119+
}
120+
121+
@Test
122+
public void updateItem_itemAddedAndShownInBothComponents() {
95123
findElement(By.id(CheckboxGroupListDataViewPage.UPDATE_ITEM)).click();
96-
Assert.assertEquals("Wrong name for updated person",
124+
125+
Assert.assertEquals("Wrong name for updated person in first Checkbox",
97126
"Jack",
98-
checkboxGroup.$("vaadin-checkbox").all().get(3).getText());
127+
checkboxGroup.$("vaadin-checkbox").all().get(0).getText());
99128

100-
// Delete item
129+
Assert.assertEquals("Wrong name for updated person in second Checkbox",
130+
"Jack",
131+
otherCheckboxGroup.$("vaadin-checkbox").all().get(0).getText());
132+
}
133+
134+
@Test
135+
public void deleteItem_itemAddedAndShownInBothComponents() {
101136
findElement(By.id(CheckboxGroupListDataViewPage.DELETE_ITEM)).click();
102-
Assert.assertEquals("Item count not expected", 3,
137+
138+
Assert.assertEquals("Unexpected item count in first Checkbox", 2,
103139
checkboxGroup.$("vaadin-checkbox").all().size());
104140

105-
// Sort order
141+
Assert.assertEquals("Unexpected item count in second Checkbox", 2,
142+
otherCheckboxGroup.$("vaadin-checkbox").all().size());
143+
}
144+
145+
@Test
146+
public void sorting_itemsSortedOnlyInOneComponent() {
106147
findElement(By.id(CheckboxGroupListDataViewPage.SORT_BUTTON)).click();
148+
107149
Assert.assertEquals("Unexpected sort order", "John,Mike,Paul",
108150
checkboxGroup.$("vaadin-checkbox").all().stream()
109151
.map(TestBenchElement::getText)
110152
.collect(Collectors.joining(",")));
111153

154+
Assert.assertEquals("Unexpected sort order", "John,Paul,Mike",
155+
otherCheckboxGroup.$("vaadin-checkbox").all().stream()
156+
.map(TestBenchElement::getText)
157+
.collect(Collectors.joining(",")));
158+
}
159+
160+
@Test
161+
public void filtering_itemsFilteredOnlyInOneComponent() {
112162
findElement(By.id(CheckboxGroupListDataViewPage.FILTER_BUTTON)).click();
113163

114-
// Filtering
115-
checkboxes = checkboxGroup.$("vaadin-checkbox").all();
164+
List<TestBenchElement> checkboxes = checkboxGroup.$("vaadin-checkbox")
165+
.all();
116166
Assert.assertEquals("Unexpected filtered checkbox count", 1,
117167
checkboxes.size());
118168
Assert.assertEquals("Unexpected filtered checkbox item", "Paul",
119169
checkboxes.get(0).getText());
170+
171+
// Verify no impact on other component bound to the same data provider
172+
checkboxes = otherCheckboxGroup.$("vaadin-checkbox").all();
173+
Assert.assertEquals("No filter expected on other CheckboxGroup bound "
174+
+ "to the same data provider", 3, checkboxes.size());
175+
Assert.assertArrayEquals(
176+
"No filtering expected on other "
177+
+ "CheckboxGroup bound to the same data provider",
178+
new String[] { "John", "Paul", "Mike" },
179+
checkboxes.stream().map(TestBenchElement::getText).toArray());
120180
}
121181
}

vaadin-checkbox-flow-parent/vaadin-checkbox-flow/src/main/java/com/vaadin/flow/component/checkbox/CheckboxGroup.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import com.vaadin.flow.data.provider.DataChangeEvent;
4141
import com.vaadin.flow.data.provider.DataProvider;
4242
import com.vaadin.flow.data.provider.DataProviderWrapper;
43+
import com.vaadin.flow.data.provider.DataViewUtils;
4344
import com.vaadin.flow.data.provider.HasDataView;
4445
import com.vaadin.flow.data.provider.HasListDataView;
4546
import com.vaadin.flow.data.provider.IdentifierProvider;
@@ -154,7 +155,7 @@ public CheckboxGroupListDataView<T> setItems(
154155
@Override
155156
public CheckboxGroupListDataView<T> getListDataView() {
156157
return new CheckboxGroupListDataView<>(this::getDataProvider, this,
157-
this::identifierProviderChanged);
158+
this::identifierProviderChanged, (filter, sorting) -> reset());
158159
}
159160

160161
/**
@@ -209,6 +210,7 @@ public void setItems(Stream<T> streamOfItems) {
209210
@Deprecated
210211
public void setDataProvider(DataProvider<T, ?> dataProvider) {
211212
this.dataProvider.set(dataProvider);
213+
DataViewUtils.removeComponentFilterAndSortComparator(this);
212214
reset();
213215

214216
if (dataProviderListenerRegistration != null) {
@@ -448,6 +450,7 @@ protected boolean hasValidValue() {
448450
return selectedItems.stream().allMatch(itemEnabledProvider);
449451
}
450452

453+
@SuppressWarnings("unchecked")
451454
private void reset() {
452455
// Cache helper component before removal
453456
Component helperComponent = getHelperComponent();
@@ -461,9 +464,11 @@ private void reset() {
461464

462465
synchronized (dataProvider) {
463466
final AtomicInteger itemCounter = new AtomicInteger(0);
464-
getDataProvider().fetch(new Query<>()).map(this::createCheckBox)
467+
468+
getDataProvider().fetch(DataViewUtils.getQuery(this))
469+
.map(item -> createCheckBox((T) item))
465470
.forEach(component -> {
466-
add(component);
471+
add((Component) component);
467472
itemCounter.incrementAndGet();
468473
});
469474
lastFetchedDataSize = itemCounter.get();
@@ -613,4 +618,5 @@ private IdentifierProvider<T> getIdentifierProvider() {
613618
private void identifierProviderChanged(IdentifierProvider<T> identifierProvider) {
614619
keyMapper.setIdentifierGetter(identifierProvider);
615620
}
621+
616622
}

vaadin-checkbox-flow-parent/vaadin-checkbox-flow/src/main/java/com/vaadin/flow/component/checkbox/dataview/CheckboxGroupListDataView.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@
1919
import com.vaadin.flow.data.provider.AbstractListDataView;
2020
import com.vaadin.flow.data.provider.DataProvider;
2121
import com.vaadin.flow.data.provider.IdentifierProvider;
22+
import com.vaadin.flow.function.SerializableBiConsumer;
23+
import com.vaadin.flow.function.SerializableComparator;
2224
import com.vaadin.flow.function.SerializableConsumer;
25+
import com.vaadin.flow.function.SerializablePredicate;
2326
import com.vaadin.flow.function.SerializableSupplier;
2427

2528
/**
@@ -42,11 +45,15 @@ public class CheckboxGroupListDataView<T> extends AbstractListDataView<T> {
4245
* data provider supplier
4346
* @param checkboxGroup
4447
* checkbox group instance for this DataView
48+
* @param filterOrSortingChangedCallback
49+
* callback, which is being invoked when the CheckboxGroup's
50+
* filtering or sorting changes, not <code>null</code>
4551
*/
4652
public CheckboxGroupListDataView(
4753
SerializableSupplier<DataProvider<T, ?>> dataProviderSupplier,
48-
CheckboxGroup<T> checkboxGroup) {
49-
super(dataProviderSupplier, checkboxGroup);
54+
CheckboxGroup<T> checkboxGroup,
55+
SerializableBiConsumer<SerializablePredicate<T>, SerializableComparator<T>> filterOrSortingChangedCallback) {
56+
super(dataProviderSupplier, checkboxGroup, filterOrSortingChangedCallback);
5057
}
5158

5259
/**
@@ -60,12 +67,16 @@ public CheckboxGroupListDataView(
6067
* @param identifierChangedCallback
6168
* callback method which should be called when identifierProvider
6269
* is changed
70+
* @param filterOrSortingChangedCallback
71+
* callback, which is being invoked when the CheckboxGroup's
72+
* filtering or sorting changes, not <code>null</code>
6373
*/
6474
public CheckboxGroupListDataView(
6575
SerializableSupplier<DataProvider<T, ?>> dataProviderSupplier,
6676
CheckboxGroup<T> checkboxGroup,
67-
SerializableConsumer<IdentifierProvider<T>> identifierChangedCallback) {
68-
super(dataProviderSupplier, checkboxGroup);
77+
SerializableConsumer<IdentifierProvider<T>> identifierChangedCallback,
78+
SerializableBiConsumer<SerializablePredicate<T>, SerializableComparator<T>> filterOrSortingChangedCallback) {
79+
super(dataProviderSupplier, checkboxGroup, filterOrSortingChangedCallback);
6980
this.identifierChangedCallback = identifierChangedCallback;
7081
}
7182

0 commit comments

Comments
 (0)