@Route("backoffice/offers/:offer-id")
@RouteAlias("backoffice/offers/new")
public class OfferView extends VerticalLayout implements BeforeEnterObserver {
After creating a new “Offer” via /offers/new I want to navigate to the new id based url like /offers/1. The save button calls this method:
private void saveOffer(OfferDto dto) {
offerService.save(dto);
UI.getCurrent().navigate(OfferView.class, new RouteParam("offer-id", offerId));
The navigation in browser works, but then the old UI instance is reused. So when beforeEnter is called, it uses same UI instance with all old children attached to it:
@Override
public void beforeEnter(BeforeEnterEvent event) {
// Calling getChildren() shows the old elements
In comparison, if I hit the refresh button in the browser, I get a new UI instance and getChildren()is empty. This is what I want.
Same problem, when using History API to modify the url and then execute UI.getCurrent().getPage().reload();.
Why is the UI reused and what can I do to navigate the user from the RouteAlias to the Route url?
The topmost component in any component hierarchy. There is one UI for every Vaadin instance in a browser window. A UI may either represent an entire browser window (or tab) or some part of a html page where a Vaadin application is embedded.
The UI instance is not recreated during navigation; a new instance is needed only when you access the page directly (type URL in the browser) or by reload the page (F5).
Thank you. But why does the view dont have children anymore, when navigating from a different view?
I have an overview view:
@Route("backoffice/offers")
public class OffersView {
// Navigation
grid.asSingleSelect().addValueChangeListener(event ->
UI.getCurrent().navigate(OfferView.class, new RouteParam("offer-id", event.getValue().id()))
);
…
And whenever the user is navigating from here, the getChildren in the OfferView is empty.
As a background:
I am adding elements via add() to the view in the beforeEnter method:
@Route("backoffice/offers/:offer-id")
@RouteAlias("backoffice/offers/new")
public class OfferView...
@Override
public void beforeEnter(BeforeEnterEvent event) {
Offer offer = event.getRouteParameters().get("offer-id").map(service::findById).orElseThrow();
add(new OfferDetailsComponent(offer));
With this approach it adds additional components to the view. Am I maybe using this wrongly? My problem is, that I only get the offer’s ID on the beforEnter Event and must load the data from backend.
Actually, you are navigating to the same view, so it is up to you to clear the contents.
A different approach could be to define two views, one backoffice/offers/new and the other for backoffice/offers/:offer-id. This way, when you navigate from backoffice/offers/new to backoffice/offers a new instance of the latter will be created.
Do I understand correctly, that when navigating from one view to another, it will generate a new view instance, but when navigating to the same view it will not?
Using different view classes is of course a solution, but is there a way to somehow force a recreation of the view?