Dialog won't open after redirect
Description
I have a Spring Security in place which shows LoginRoute when no user is logged in. The LoginRoute is just a simple Div which opens a LoginDialog on attach. The problem is that the dialog won't open in certain cases. More precisely:
- The dialog opens when you navigate straight for LoginRoute
- The dialog won't open when you navigate to a protected view first, which then redirects to LoginRoute
Debugging the issue I discovered that in Dialog.ensureAttached(), in the second use-case the location change trigger is PROGRAMMATIC, the UI registration listener gets unregistered and the dialog is never attached.
Expected outcome
The dialog should be shown regardless of what kind of navigation chain occurred.
Minimal reproducible example
Create a route which redirects to another route, which then opens a dialog.
Steps to reproduce
I don't have a Spring-Boot+Security project but the issue is easily reproducible in a simpler project:
- git clone https://github.com/mvysny/vaadin-simple-security-example
- Edit LoginRoute and add the following lines to the constructor:
final Dialog dlg = new Dialog();
dlg.setHeaderTitle("Won't be shown");
dlg.add(new Span("Foo"));
dlg.setCloseOnOutsideClick(false);
dlg.open();
- Start the app. The app navigates to WelcomeRoute which is protected by security and therefore a redirect to LoginRoute occurs. The LoginRoute tries to open the dialog but the dialog won't open.
This bug is also unit-testable easily.
Environment
Vaadin version(s): 24.3.6 OS: Ubuntu 23.10
Browsers
No response
Even simpler steps to reproduce: paste this to the Skeleton Starter:
@Route
public class MainView extends VerticalLayout implements BeforeEnterObserver {
@Override
public void beforeEnter(BeforeEnterEvent beforeEnterEvent) {
beforeEnterEvent.forwardTo(SecondView.class);
}
@Route("second")
public static class SecondView extends VerticalLayout {
public SecondView() {
new Dialog("Foo").open();
add(new Span("Look Ma, no dialog. Refresh the page to see the dialog"));
}
}
}
Workaround is to add the Dialog manually to the UI:
@Route
public class MainView extends VerticalLayout implements BeforeEnterObserver {
@Override
public void beforeEnter(BeforeEnterEvent beforeEnterEvent) {
beforeEnterEvent.forwardTo(SecondView.class);
}
@Route("second")
public static class SecondView extends VerticalLayout {
public SecondView() {
final Dialog dlg = new Dialog("Foo");
dlg.open();
UI ui = UI.getCurrent();
ui.beforeClientResponse(ui, context -> {
if (dlg.getElement().getNode().getParent() == null
&& dlg.isOpened()) {
ui.addToModalComponent(dlg);
ui.setChildComponentModal(dlg, dlg.isModal());
}
});
add(new Span("Look Ma, no dialog. Refresh the page to see the dialog"));
}
}
}
I wonder what breaks.... :thinking: