Hi there,
i'd like to create a link as a cell in my grid.
In my main class i create a grid
grid.addColumn(new ComponentTemplateRenderer<>(device -> new RouterLink(device.getName(), DeviceCard.class, device.getId())));
with
@Route(value = "", layout = DeviceSection.class)
public class DeviceCard extends VerticalLayout implements HasUrlParameter<Long>, HasDynamicTitle {...}
But it throws:
[com.vaadin.router.InternalServerError] (default task-8) There was an exception while trying to navigate to 'devices/13672': java.lang.IllegalStateException: Unregistered node was not found based on its id. The tree is most likely corrupted.
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.StateTree.unregister(StateTree.java:185)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.StateNode.handleOnDetach(StateNode.java:429)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.StateNode.visitNodeTreeBottomUp(StateNode.java:380)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.StateNode.onDetach(StateNode.java:208)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.StateNode.setParent(StateNode.java:167)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.nodefeature.NodeFeature.detatchPotentialChild(NodeFeature.java:94)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.nodefeature.StateNodeNodeList.remove(StateNodeNodeList.java:62)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.nodefeature.ElementChildrenList.remove(ElementChildrenList.java:54)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.nodefeature.ElementChildrenList.remove(ElementChildrenList.java:26)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.nodefeature.NodeList.clear(NodeList.java:371)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.nodefeature.ElementChildrenList.clear(ElementChildrenList.java:59)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.dom.impl.AbstractNodeStateProvider.removeAllChildren(AbstractNodeStateProvider.java:104)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.dom.Node.removeAllChildren(Node.java:332)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.ui.grid.GridTemplateRendererUtil$ComponentDataGenerator.destroyAllData(GridTemplateRendererUtil.java:111)
at java.base/java.lang.Iterable.forEach(Iterable.java:75)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.ui.grid.Grid$GridDataGenerator.destroyAllData(Grid.java:629)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.data.provider.DataCommunicator.handleDetach(DataCommunicator.java:330)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1378)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.StateNode.fireDetachListeners(StateNode.java:506)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.StateNode.handleOnDetach(StateNode.java:431)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.StateNode.visitNodeTreeBottomUp(StateNode.java:380)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.StateNode.onDetach(StateNode.java:208)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.StateNode.setParent(StateNode.java:167)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.nodefeature.NodeFeature.detatchPotentialChild(NodeFeature.java:94)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.nodefeature.StateNodeNodeList.remove(StateNodeNodeList.java:62)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.nodefeature.ElementChildrenList.remove(ElementChildrenList.java:54)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.dom.impl.AbstractNodeStateProvider.removeChild(AbstractNodeStateProvider.java:114)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.dom.Node.removeChild(Node.java:302)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.flow.dom.Element.removeFromParent(Element.java:573)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.ui.UIInternals.removeFromParent(UIInternals.java:626)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.ui.UIInternals.showRouteTarget(UIInternals.java:598)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.router.NavigationStateRenderer.handle(NavigationStateRenderer.java:161)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.router.Router.navigate(Router.java:149)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.router.Router.lambda$initializeUI$be6f7aff$1(Router.java:80)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.server.communication.rpc.NavigationRpcHandler.handle(NavigationRpcHandler.java:62)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.server.communication.ServerRpcHandler.handleInvocationData(ServerRpcHandler.java:359)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.server.communication.ServerRpcHandler.lambda$handleInvocations$0(ServerRpcHandler.java:349)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1378)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:349)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:287)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:88)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1517)
at deployment.demo-1.0-SNAPSHOT.war//com.vaadin.server.VaadinServlet.service(VaadinServlet.java:351)
at javax.servlet.api//javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
Thanks!
I'm experiencing the same issue: clicking on a RouterLink throws:
IllegalStateException: Unregistered node was not found based on its id. The tree is most likely corrupted.
Any feedback on this? Steps to reproduce:
@Route("")
public class Foo extends Div {
public Foo() {
Grid<String> grid = new Grid<>();
grid.addColumn(new ComponentTemplateRenderer<>(x -> new RouterLink("Bar", Bar.class)));
grid.setItems("x");
this.add(grid);
}
}
@Route("bar")
public class Bar extends Div {}
then click on the "Bar" link.
I'm wondering if we should add an optimized RouterLinkRenderer for this.
EDIT: I know there is a bug here to fix, but first I just feel that this is such a common use case for Grid to have a cell that has links to other parts of the App that it could be made even easier.
The problem in this case is that we detach/unregister the component and then fireDetachListeners before setting the parent to null which runs DataCommunicator::handleDetach that does a setParent(null) that sees that we are attached as we haven't set parent as null yet as we are on the onDetach() step which leads to us calling unregister() on a node that is already unregistered, but as such not marked with a parent==null which makes it seem that it is still attached.
showRouteTarget
removeAllChildren::Node
removeAllChildren::AbstractNodeStateProvider
clear::ElementChildrenList
clear::NodeList
remove
remove
remove
detatchPotentialChild
setParent
onDetach
visitNodeTreeBottomUp
--- handleOnDetach
unregister (returns)
--- handleOnDetach (runs fireDetachListeners) ->
fireDetachListeners
forEach
handleDetach
destroyAllData
forEach
destroyAllData
removeAllChildren
removeAllChildren
clear
clear
remove
remove
remove
detatchPotentialChild
setParent
onDetach
visitNodeTreeBottomUp
handleOnDetach
unregister
Thank you @caalador for the analysis! Do you think there's a chance to address this for alpha 16?
I would expect it to be. I need to add some tests, but the fix seems to work.
Added ticket for the renderer: #3246
Most helpful comment
I'm wondering if we should add an optimized
RouterLinkRendererfor this.EDIT: I know there is a bug here to fix, but first I just feel that this is such a common use case for
Gridto have a cell that has links to other parts of the App that it could be made even easier.