flow icon indicating copy to clipboard operation
flow copied to clipboard

Navigating to the same Route does not work after using BeforeLeaveEvent.postpone

Open lgf10 opened this issue 2 years ago • 9 comments

Description of the bug

When navigating to a route using ContinueNavigationAction.proceed, the route can not be navigated to again. This is due to UIIntenals.lastHandledNavigation not being cleared, which skips navigation in UI.navigate.

A simple example of this is a page that shows a confirmation dialog when leaving and that can be navigated to from itself (e.g. a header button present in the RouterLayout). After the first navigation the confirmation dialog is not shown anymore (and the navigation is not performed).

Expected behavior

Navigation to the same page is not prevented (the behaviour should be the same as when not using BeforeLeaveEvent.postpone). During this navigation, observers like beforeLeave should be triggered.

Minimal reproducible example

Pressing the button has no effect after the first navigation:

@Route("sample")
public class Sample extends Div implements BeforeLeaveObserver {

    private static final long serialVersionUID = 1L;

    public Sample() {
        add(new Button("Navigate", e -> UI.getCurrent().navigate("sample")));
    }

    @Override
    public void beforeLeave(BeforeLeaveEvent event) {
        var action = event.postpone();
        var dialog = new Dialog();
        dialog.add(new Button("Proceed", e -> {
            action.proceed();
            dialog.close();
        }));
        dialog.open();
    }
}

Manually clearing the last handled navigation in afterNavigation fixes the issue:

@Route("sample")
public class Sample extends Div implements BeforeLeaveObserver, AfterNavigationObserver {

    private static final long serialVersionUID = 1L;

    public Sample() {
        add(new Button("Navigate", e -> UI.getCurrent().navigate("sample")));
    }

    @Override
    public void beforeLeave(BeforeLeaveEvent event) {
        var action = event.postpone();
        var dialog = new Dialog();
        dialog.add(new Button("Proceed", e -> {
            action.proceed();
            dialog.close();
        }));
        dialog.open();
    }

    @Override
    public void afterNavigation(AfterNavigationEvent event) {
        UI.getCurrent().getInternals().clearLastHandledNavigation();
    }
}

Versions

Vaadin: 24.1.0.rc2 Flow: 24.1.0.rc2 Java: Eclipse Adoptium 17.0.6 OS: amd64 Windows 10 10.0

lgf10 avatar Jun 07 '23 15:06 lgf10

For clarification: this behaviour is not new in 24.1.0, but also exists with 23.3.12

leluna avatar Jun 09 '23 06:06 leluna

@leluna this is a valid bug, thanks for reporting it! One thing is not clear for me is - if you navigate to a route different from sample, the code above should work for you, right? What is the purpose you want to navigate to the same route? Is it only for demo purpose or is a real use case?

mshabarov avatar Jun 13 '23 10:06 mshabarov

if you navigate to a route different from sample, the code above should work for you, right?

Yes, the issue only occurs for navigating to the same route

What is the purpose you want to navigate to the same route? Is it only for demo purpose or is a real use case?

We have run into this issue in several of our applications. Using documents as simple example:

  • Existing documents are accessible via an ID /documents/1234
  • Creating a new document uses the URL /documents/new
  • If the user has edited the document before saving, they will be prompted when leaving the page
  • A "New document" button is always shown in the header (created by the RouterLayout)

Since the "New document" button is available while already creating a document (and thus already being on the target route), it is possible to run into this issue.

lgf10 avatar Jun 13 '23 11:06 lgf10

This is still occuring with 24.5.8. We are calling UI.getCurrent().getInternals().clearLastHandledNavigation() in all views which I'd love to remove :)

leluna avatar Dec 20 '24 13:12 leluna

This behavior only occurs if vaadin.react.enable is set to false. This is caused by the fact that in BeforeLeaveEvent#proceed, clearLastHandledNavigation is only called if react is enabled (https://github.com/vaadin/flow/blob/bc78ab705d3bd7b6c805149fbac8a7eaea008d62/flow-server/src/main/java/com/vaadin/flow/router/BeforeLeaveEvent.java#L101)

Just for my curiosity: Is there any reason why it is only called if react is not enabled?

leluna avatar Mar 13 '25 08:03 leluna

This ticket/PR has been released with Vaadin 24.7.1.

vaadin-bot avatar Mar 27 '25 15:03 vaadin-bot

This ticket/PR has been released with Vaadin 24.6.8.

vaadin-bot avatar Apr 15 '25 07:04 vaadin-bot

Hi @mshabarov I’ve run into the same issue – even though I’m already using Vaadin 24.7.4 (the latest version), where this bug is supposed to be fixed according to the changelog.

I’ve tested it in both Chrome and Firefox, and unfortunately, the issue still persists.

To stay close to @lgf10 example, I created a simple sample class and tried several variations, but nothing worked so far.

Even the call to UI.getCurrent().getInternals().clearLastHandledNavigation(); doesn’t work for me.

Here’s my sample class:

@Route("sample")
public class Sample extends VerticalLayout implements AfterNavigationObserver {

    public Sample() {
        add(new Button("Re-Navigate", e -> UI.getCurrent().navigate("sample")));
        add(new Text(" Last loading time-millis.: " + System.currentTimeMillis()));
    }

    @Override
    public void afterNavigation(final AfterNavigationEvent afterNavigationEvent) {
        UI.getCurrent().getInternals().clearLastHandledNavigation();
    }
}

If anyone has a workaround or can confirm that it’s working properly for them with 24.7.4, I’d really appreciate any input.

https://github.com/user-attachments/assets/471f4fda-f93e-4937-8043-89712dec46ca

mr-enabi avatar May 18 '25 15:05 mr-enabi

Reopened for further investigation.

mshabarov avatar May 20 '25 09:05 mshabarov

Any updates on my issue? @mshabarov @leluna @caalador

mr-enabi avatar Jan 05 '26 17:01 mr-enabi