Skip to content

Commit 8536316

Browse files
vaadin-botcaalador
andauthored
fix: readding component that on detach removes components (#17837) (#17847)
Fixes the case where a component is readded to the same parent and at the same time in a detachListener removes components from the parent. Fixes #16741 Co-authored-by: caalador <[email protected]>
1 parent 81e3b98 commit 8536316

File tree

3 files changed

+27
-1
lines changed

3 files changed

+27
-1
lines changed

flow-server/src/main/java/com/vaadin/flow/dom/Node.java

+5
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,11 @@ public N insertChild(int index, Collection<Element> children) {
383383
}
384384
}
385385
child.removeFromParent();
386+
// If detach of component removes other components adjust insert
387+
// target
388+
if (insertIndex > getChildCount()) {
389+
insertIndex = getChildCount();
390+
}
386391
getStateProvider().insertChild(node, insertIndex, child);
387392
ensureChildHasParent(child, true);
388393
}

flow-server/src/main/java/com/vaadin/flow/dom/impl/AbstractNodeStateProvider.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,9 @@ public Element getChild(StateNode node, int index) {
100100
@Override
101101
public void insertChild(StateNode node, int index, Element child) {
102102
assert index >= 0;
103-
assert index <= getChildCount(node); // == if adding as last
103+
// == if adding as last
104+
assert index <= getChildCount(node)
105+
: "index " + index + " outside range " + getChildCount(node);
104106

105107
getChildrenFeature(node).add(index, child.getNode());
106108
if (child.getComponent().isPresent()) {

flow-server/src/test/java/com/vaadin/flow/component/ComponentTest.java

+19
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,25 @@ public void testAttachListener_eventOrder_childFirst() {
680680
parent.assertAttachEvents(1);
681681
}
682682

683+
@Test
684+
public void testAttachDetach_children() {
685+
UI ui = new UI();
686+
TestComponentContainer parent = new TestComponentContainer();
687+
TestComponent child1 = new TestComponent();
688+
TestComponent child2 = new TestComponent();
689+
TestComponent child3 = new TestComponent();
690+
parent.addAttachListener(e -> ui.add(child1, child2, child3));
691+
parent.addDetachListener(e -> ui.remove(child1, child2, child3));
692+
693+
ui.add(parent);
694+
695+
Assert.assertEquals(4, ui.getChildren().count());
696+
697+
ui.add(parent);
698+
699+
Assert.assertEquals(4, ui.getChildren().count());
700+
}
701+
683702
@Test
684703
public void testDetachListener_eventOrder_childFirst() {
685704
UI ui = new UI();

0 commit comments

Comments
 (0)