Closed OlliTietavainenVaadin closed 2 years ago
Workaround is to recreate legacy components and not using existing instances.
@Route(value = TreeView.ROUTE, layout = MyUI.class)
public class TreeView extends VerticalLayout {
public static final String ROUTE = "tree";
public static final String TITLE = "Tree";
private String param;
private com.vaadin.ui.Button firstLegacy = new com.vaadin.ui.Button("first legacy");
private com.vaadin.ui.Button secondLegacy = new com.vaadin.ui.Button("second legacy");
private HorizontalLayout layout = new HorizontalLayout();
public TreeView() {
setAlignItems(Alignment.CENTER);
add(layout);
layout.add(wrap(firstLegacy));
Button readdFirst = new Button("(re)add first", e -> {
layout.removeAll();
layout.add(wrap(new com.vaadin.ui.Button("first legacy")));
});
Button readdSecond = new Button("(re)add second", e -> {
layout.removeAll();
layout.add(wrap(new com.vaadin.ui.Button("second legacy")));
});
add(readdFirst, readdSecond);
}
public LegacyWrapper wrap(com.vaadin.ui.Component component) {
return new LegacyWrapper(component);
}
}
The issue is not that the same component can't be added back, but that it is removed and added in the same roundtrip. What is the usecase for remove and add on a single server roundtrip?
Toggling the visibility of components without needing to keep track of which components are actually shown at the time.
Would using a legacy layout from which the components are removed and added be a possibility? If you change the demo code to
@Route(value = TreeView.ROUTE)
public class TreeView extends VerticalLayout {
public static final String ROUTE = "tree";
private com.vaadin.ui.Button firstLegacy = new com.vaadin.ui.Button("first legacy");
private com.vaadin.ui.Button secondLegacy = new com.vaadin.ui.Button("second legacy");
private com.vaadin.ui.HorizontalLayout layout = new com.vaadin.ui.HorizontalLayout();
public TreeView() {
setAlignItems(Alignment.CENTER);
add(wrap(layout));
layout.addComponent(firstLegacy);
Button readdFirst = new Button("(re)add first", e -> {
layout.removeAllComponents();
layout.addComponent(firstLegacy);
});
Button readdSecond = new Button("(re)add second", e -> {
layout.removeAllComponents();
layout.addComponent(secondLegacy);
});
add(readdFirst, readdSecond);
}
public LegacyWrapper wrap(com.vaadin.ui.Component component) {
return new LegacyWrapper(component);
}
}
Then removing and adding the components on the same roundtrip works as expected.
Would using a legacy layout from which the components are removed and added be a possibility? If you change the demo code to
...
Then removing and adding the components on the same roundtrip works as expected.
No. Here's the answer I got from the priorizer:
In my opinion I should use MPR to switch layer by layer from Vaadin 8 to Vaadin 14 (like an onion). This circumstance breaks this strategy a bit. Of course is recreation an option, but the more complex these recreated components are, I have to think/remember more about other things. It would be easier, if MPR works as expected (in this special case).
Just a note on the issue and why this is happening.
As the problem is not really clear on what should happen to get the FrameWork to generate a hierarchy change there is the working workaround where the wrappers are not changed on the add/remove e.g.
public static final String ROUTE = "tree";
private LegacyWrapper firstLegacy = wrap(new com.vaadin.ui.Button("first legacy",clickEvent -> System.out.println("Legacy click!")));
private LegacyWrapper secondLegacy = wrap(new com.vaadin.ui.Button("second legacy"));
private HorizontalLayout layout = new HorizontalLayout();
public TreeView() {
setAlignItems(Alignment.CENTER);
add(layout);
layout.add(firstLegacy);
Button readdFirst = new Button("(re)add first", e -> {
layout.removeAll();
layout.add(firstLegacy);
});
Button readdSecond = new Button("(re)add second", e -> {
layout.removeAll();
layout.add(secondLegacy);
});
add(readdFirst, readdSecond);
}
public LegacyWrapper wrap(com.vaadin.ui.Component component) {
return new LegacyWrapper(component);
}
The best I can come up with is to add a new static method to LegacyWrapper that would then be used in this case in wrap(...)
so it would look like:
public LegacyWrapper wrap(com.vaadin.ui.Component component) {
return LegacyWrapper.getWrapper(component);
}
If you try to re-add a legacy component to a Flow layout inside a new LegacyWrapper instance, the component will not show up in the UI. Example to reproduce:
Instructions to reproduce: click buttons "(re)add first" and "(re)add second" to see - when you try to re-add a component that is currently in the UI, the component will disappear.