/level1/level2/.. URLs, View Hierarchy, Navigator, UriFragmentManager CHAOS

I am struggling for second day with navigation philosophy of vaadin with the Navigator and UriFragmentManager upside-down idea. I’d expect something more like React rather than flat URI path to views relations.

Consider following URLs and how they are represented in my scenario:
[b]
/fruit/ - view
/fruit/apple - view
/fruit/orange - view

/vegetable/ - view
/vegetable/tomato - view
/vegetable/potato - view
[/b]

The first glance at vaadin architecture gives a human perception that there is a mechanism to deal with this. I would expect that I can create a main UI with content which has 2 buttons using navigator(navigateTo
/fruit
and
/vegetable
), navigator itself would be created with UI level component reference where the view will be displayed. So as we’ve already created and used single instance of Navigator(more on that later).

Then Within the
/vegetable
view I also have two buttons pointing to
/vegetable/tomato
and
/vegetable/cherry
views
so I

created second navigator
which is created again with
/vegetable
view level component to display subviews and created two buttons using navigator(navigateTo
/vegetable/tomato
and
/vegetable/potato
).

When I traverse with buttons clicking via browser I get perception of hierarchy:

click ‘vegetable’ on UI → vegetable subview appears with ‘tomato’ and ‘potato’ buttons
click ‘tomato’ → tomato subsubview appears.

While the browser address bar is changed correspondingly from:

/
to[b]

[/b]
/vegetable/
to
/vegetable/tomato

So far so good, now lets bookmark
/vegetable/tomato


What happens if I open bookmark? Exactly! We would expect main UI with /vegetable subview inside and /vegetable/tomato subsubview within. However what we get is the main UI which just displays /vegetable/tomato subsubview, but does not have /vegetable subview. This happens because there seems to be no notion of hierarchy so subsubview = normal view in terms of url resolution. So on /vegetable/tomato request main UI is hit and top level nagivator intended for /vegetable or /fruit views actually displays /vegetable/tomato view on the root level.

[b]
Questions:

  1. All I want is for multilevel URL resolution correspond to construction of nested hierachical views. Is this possible to achieve or I am trying to do navigation not in Vaadin style? Multilevel URLs capturing states are important for bookmarking. How do you develop SPAs with multilevel URLs bookmarking?
    [/b]

  2. Should I continue and replace the useless(IMO) UriFragmentManager with my own implementation? Along the way probably ViewResolver and Navigator as well? All of this will be needed to support nested view structure recognition when typing to address bar multilevel URL, so it would literally recreate entire view hierarchy.

  3. Vaadin site itself has flat structure, so the ‘/forum’ address is not under ‘/community’, yet within the menu on UI it is , when writing this post the URL is:
    https://vaadin.com/forum#!/thread/new/1007558 , hashbang precedes ‘thread’, however in my simple example hashbang precedes the very first level, so why /forum is not preceded by #! (#!forum/thread/new/1007558)? Something else used under hood? Or /forum and /community are both standalone UIs with their own navigators? Can I disable hashbang? Only Vaadin seem to care about it.

  4. Every tutorial I read implies this invisible ghost notion of a SINGLE Navigator per UI, why is this so? Why Navigator class is so stupid that the component which content is replaced with view is only set in constructor. Why it cannot have method signature navigateTo with component paremeter for view display? This implies that you cannot reuse the same instance of Navigator for different components of different view displays which is why
    I NEED MULTIPLE Navigators.
    This notion not just embedded in people minds it is also embedded in Spring Boot Vaadin Starter, guess what → I don’t use SpringNavigator because the guy is singleton and you cannot init it with desired component again, but the idea is fiercefully pushed. The SpringNavigator like normal Navigator has no means to change the component where view is to be displayed after they’ve been constructed. But then again @SpringViewDisplay introduced in SpringBoot also has recommendation of being ever only single. I haven’t investigated how it works but I believe it is simillar to component which we pass to standard Navigator. This philosophy of one level UI and one dynamic display area is somewhat off.

I found https://vaadin.com/forum#!/thread/1851565 and a ticket closed 4 years ago https://github.com/vaadin/framework/issues/2930. Is that really how all are doing sub navigation? Tons of inheritance and endless manually created combinations? I am crying.

Hey Anton,

without considering all aspects of your question, the navigation structure of Vaadin is by default Flat. It should be considered mainly as url to view mapping.

It’s not uncommon to have large applications define their view structure with dot-notation. Quite often especially in larger apps the view structure could be as follows:

settings.user
settings.user.details

inbox
inbox.write
inbox.read

customers
customers.statistics

etc.

In this case the functionality is exactly the same as with / separator, only with the difference that the reminder of the view name part is not considered as parameter. Then, what usually happens is that there is a UI that sets up the menuing structure that corresponds the level of navigable elements. For example on the “left hand side menu” it’s quite common to have things which are at the bottom level of navigation. Things like settings, inbox, customers… At the very top of the window there usually are the second level navigation items like user, write, read, statistics. Out of these only the ones are visible which belong to the currently selected main level item. Finally, if third level is present, it’s sometimes visualised as a tab of the view, for example the ‘details’ under the user item could be a tab.

The ViewDisplay is intended to be the view holder. It’s purpose is not to change every time a view is navigated into but rather it’s the object that hosts the view and not necessarily even a component. In my above example the UI structure could be such that it has a top header, left main menu and then reminder of the space is used by a component implementing the view display. Whenever main menu item, top header item or tab is clicked, an event will be sent out of which all the menu elements requiring to show the currently selected view will be refreshed. Also the UriFragment handling should be event based, when it changes, an event is fired that is handled similarly.

Something like the above is quite often seen within the project foundation of any Vaadin project. The question is, should something like this be more supported out of the box by the framework. In most of the cases yes, but there are also many projects that benefit from having the mapping as simple as possible as many apps have very special requirements for navigation.

Good points by Peter. I just wanted to add that if you are using Vaadin 8, there’s support for the HTML 5 History API (there’s an
add-on
for 7 as well):

// push state:
Button button = new Button("Go to page 1");
button.addClickListener(e -> {
    // URL will change to .../page1
    Page.getCurrent().pushState("page1");
});

// pop state:
Page.getCurrent().addPopStateListener(event -> {
    String uri = event.getUri();
    // ... update the UI accordingly
});



There’s an
issue
on GitHub about making Navigator use this. Give a thumbs up to the issue if you think it’d be valuable for you.

This helped me alot. I’ve been trying to figure out the
philosophy UI’s and navigation
for a while. Love the description by Peter Lehto. Maybe something like that could be added to the Navigating an Application part of the book.

The book suggests a different idea to naviagtion though. See, https://vaadin.com/docs/-/part/framework/application/application-architecture.html. Under the section titled “View Navigation” these look like four UI’s rather than view’s within a UI! And if these are four views then the Main View would require a second Navigator to navigate it’s view. Is that when you’re meant to implement a custom view display?


Onto the URL naviagtion,

I wanted to do what Anton Alegol described by using /UI/view rather than using a #!.

For example I want /customers/customer/23 to display the customer with id 23. That’s easy to do with the History API with a simple Page.getCurrent().pushState(“/customers/customer/” + id);

I’m using spring boot with Vaadin so to allow for browser navigation I created a @Requestmapping()

@RequestMapping("/customers/customer/{id}") public String forwardToVaadin(@PathVariable("id") Integer id){ return "redirect:/customers?customer=" + id; } Note the redirect path.

I found the use of “redirect” rather than “forward” is necessary as the URL is two levels high and Vaadin bootstrap.js uses a relative request from the browser to the UI which is at /* not /customers.

When the VaadinRequest comes through I check the variable “customer” and if it’s set I navigate to the view. Then again use the history app to point the browser to the correct path.

And I’d really love to know if there is a better way of doing the URL translation! Surely there is.