I have this code:
void addToSlot(String name, Component... components) {
for (Component component : components) {
var element = component.getElement();
element.setAttribute(AttributeNames.SLOT, name);
this.getElement().appendChild(element);
}
}
And it works the first time, but after navigating away and back to the same route I get this exception:
java.lang.IllegalArgumentException: Trying to detach an element from parent that does not have it.
at com.vaadin.flow.dom.impl.AbstractNodeStateProvider.removeChild(AbstractNodeStateProvider.java:123)
at com.vaadin.flow.dom.Node.removeChild(Node.java:332)
at com.vaadin.flow.dom.Element.removeFromParent(Element.java:577)
at com.vaadin.flow.dom.Node.insertChild(Node.java:249)
at com.vaadin.flow.dom.Node.appendChild(Node.java:141)
at it.axians.vaadin.mixins.HasSlots$1.add(HasSlots.java:63)
How can I prevent this?
Are the components stored over the navigation?
Seems like the Components are keeping their parent element where as the parent element is rebuilt?
What do you mean "stored" and "rebuilt"?
Is there a reference for the components so that during navigation they are not cleand/regenerated and when navigating back they are attached to a clean element instance that doesn't have any children registered.
Would you possibly have a starter with the issue?
Some components might be Spring beans in the UI scope. A workaround I've found is to use removeFromTree on detach, but I'm not sure if this has side effects.
I have the same problem with a Grid component. The grid is part of a tab sheet using Tabs. To not having all the tab contents in the DOM, I remove all components below grid and only add the one content I need. All components are stored in a map to do not create the whole content every time I switch the tab. Using this approach I get the exception from a component (for example a button) in a cell of the grid after switching to the corresponding tab the second time (first time the grid was added initially, second time it was re-attached).
I had a similar issue as @cdir.
We use a grid as well, it`s data provider is being updated by a ComponentEvent listener. If it is updated and I navigate to another page, the exception is thrown.
I was able to fix it by executing the update of the data provider in a ui. access call, like this (kotlin):
content.ui.ifPresent {
it.access {
lineItemDataProvider.setCurrentId(currentId)
lineItemDataProvider.refreshAll()
}
}
I hope this helps
Most helpful comment
I have the same problem with a Grid component. The grid is part of a tab sheet using Tabs. To not having all the tab contents in the DOM, I remove all components below grid and only add the one content I need. All components are stored in a map to do not create the whole content every time I switch the tab. Using this approach I get the exception from a component (for example a button) in a cell of the grid after switching to the corresponding tab the second time (first time the grid was added initially, second time it was re-attached).