When a user clicks multiple sidebar navigation items rapidly (before the current view finishes loading), View.QueryParametersChangeEvent fires with empty query parameters. The navId parameter is missing on the server side, even though the browser URL correctly shows ?navId=xxx.
This causes the view to display its system/default title instead of the navigation-configured custom title.
How to Reproduce
- Create a sidebar menu with
RouterLinkitems, each having?navId=<value>in the URL - Click menu item A (URL:
/view-a?navId=abc) — view loads correctly,navId=abcreceived - Before A finishes loading, quickly click menu item B (
/view-b?navId=def) - Quickly click menu item C or back to A
-
Result:
QueryParametersChangeEvent.getQueryParameters().getSingleParameter("navId")returnsOptional.empty()— even though browser URL has?navId=abc
Code
Sidebar link creation (using JmixListMenu + RouterLink):
public class AppListMenu extends JmixListMenu {
@Override
protected RouterLink createMenuItemComponent(ListMenu.MenuItem menuItem) {
RouterLink routerLink = super.createMenuItemComponent(menuItem);
if (menuItem instanceof BadgeMenuItem badge) {
// Setting href manually with navId
routerLink.getElement().setAttribute("href", badge.getUrl());
// URL example: /applicants?navId=abc123
}
return routerLink;
}
}
Receiving view:
public abstract class AbstractNavigationListView<E> extends StandardListView<E> {
private Navigation navigation;
@Override
public @NonNull String getPageTitle() {
if (navigation != null) {
return navigation.getShortName(); // custom navigation title
}
return super.getPageTitle(); // falls back to system title like "Monitoring2"
}
@Subscribe
public void onQueryParametersChange(final QueryParametersChangeEvent event) {
String crcId = event.getQueryParameters()
.getSingleParameter("navId").orElse(null);
// crcId is NULL during rapid clicking!
setNavigation(navigationService.getByCRCId(crcId));
}
}
What We Tried
-
navId == null→ return (skip) — preventsnavigationfrom being set tonull, but the view still loads without proper navigation context on first open -
Replaced
setAttribute("href")withRouterLink.setRoute()+setQueryParameters()— same issue persists -
JS fallback (
executeJs→ readwindow.location.search) — async, causes title flickering - Click debounce (300ms) on sidebar items — degrades UX
-
BeforeEnterObserver— Jmix AI confirmed this uses the same router lifecycle, so same race condition applies
Expected Behavior
QueryParametersChangeEvent should always contain the query parameters matching the current browser URL, regardless of navigation speed.
Actual Behavior
During rapid navigation, the event arrives with empty/missing query parameters. The browser URL is correct, but the server-side event doesn’t reflect it.
Question
- Is this a known Vaadin router limitation with rapid client-side navigation?
- Is there a recommended pattern in Jmix for reliable query parameter handling that survives rapid navigation?
- Should we use a different mechanism entirely instead of
?navIdquery parameter (e.g., route path parameter)?
Environment: Jmix 2.7.4, Vaadin 24.9.9, Java 17