Where to place the main rendering code when implementing BeforeEnterObserve

To avoid rendering a View while the user has not yet created a certain dataObject (in another View), I’ve implemented BeforeEnterObserver where I check whether this object is available. If not, I reroute to the correct view first.

While trying to make this work, I realised that placing the main code for a View in its constructor is a troublesome practice, since a constructor is called when the object is created, so the main rendering code is executed before the beforeEnter() method can be called. I note that for most of the Flow’s code examples, the code seems to be placed in the constructor, which was slightly confusing. Did I overlook something in the Vaadin Flow documentation?

I’ve also noted the AfterNavigationObserver interface and the afterNavigation() method. Is afterNavigation() the correct hook to place the main code for rendering a View when implementing BeforeEnterObserver? Or am I perhaps missing something? Thanks you.

I’ve also noted the AfterNavigationObserver interface and the afterNavigation() method. Is afterNavigation() the correct hook to place the main code for rendering a View when implementing BeforeEnterObserver?

I would say that typically yes.

I note that for most of the Flow’s code examples, the code seems to be placed in the constructor

In simple cases where you do not need to take the view lifecycle into account you can have the code in constructor, but in advanced scenarios, like in your case, it might not work that well anymore. But on the other hand that is exactly why these view lifecycle events are there.

Thank you for your prompt response, Tatu.

Addendum to all who stumble upon this post:

If you put your View rendering code in afterNavigation(…) method, make sure it is loaded only once by adding from the following example.

private boolean alreadyRendered = false;

...
...

public void afterNavigation(AfterNavigationEvent afterNavigationEvent)
{
    if (!alreadyRendered)
    {
        addHeader();
        addMainComponents();
        ...
        
        alreadyRendered = true;
    }
}