Tip: How to get page title (and view) of current page

For a help/feedback system I needed to get the title of the current page.

I wasn’t able to find anything in the documentation, but with some trial-and-error I came up with an approach that seems to work.

There might be other approaches, but wanted to share this to the group in case you need it.

         String pageTitle = null;
		 
		 // Get list of current views, the first view is the top view.
         List<HasElement> views = UI.getCurrent().getInternals().getActiveRouterTargetsChain();
         if (views.size() > 0) {
            HasElement view = views.get(0);

            // If the view has a dynamic title we'll use that
            if (view instanceof HasDynamicTitle) {
               pageTitle = ((HasDynamicTitle) view).getPageTitle().toString();
            } else {
               // It does not have a dynamic title. Try to read title from
               // annotations
               PageTitle pt = AnnotationUtils.findAnnotation(view.getClass(), PageTitle.class);
               pageTitle = pt != null ? pt.value() : null;
            }
         }

Have you tried ui.getInternals().getTitle()? The title should be available there after the navigation has been done (AfterNavigationObserver method is called).

Looks like a good solution for the most common cases. However, it doesn’t cover two cases that I can think of.

One of them is setting of the page title with UI.getCurrent().getPage().setTitle("title");. Internally, this method uses ui.getInternals().setTitle(title); and the value can be recovered with ui.getInternals().getTitle() (which only returns the value set by setTitle, it’s not necessary up to date if title is set by other means).

Another case would be updating the title with JavaScript. This is actually what the ui.getInternals().setTitle method does under the hood, too, but it could also happen from any JavaScript call that updates document.title. You can retrieve the value with a JavaScript callback:

            UI.getCurrent().getPage().executeJs("return document.title;").then(String.class,
                    title -> {
                        // do something with the title String
                    }
                    );

The callback approach will actually work for all scenarios, as it’s fetching the value from the browser, but the downside of it is that it requires a round trip from the client to the server.

This can be done better with javascript. With your approach you have different implementations for HasDynamicTitle-Views, views with @PageTitle annotation, and views without both (which you have not implemented yet).

By reading document.title with javascript it will always be the same approach, and give you the current page title even if it is a dynamic one.

UI.getCurrent().getPage().executeJs("return document.title").then(String.class, pageTitle -> {
	Notification.show(String.format("Page title: '%s'", pageTitle));
})

Edit: looks like Olli beat me to it, haha :slight_smile:

Thank you very much for your feedback, very much appreciated and very informative.

I totally missed getTitle from getInternals() which seems to be the best way to go if the frontend doesn’t change the title (thanks Stefan). That way, we don’t need to do a frontend roundtrip to get the title.

Based on further consideration, I think we’ll be going with UI.getCurrent().getInternals().getActiveRouterTargetsChain() and pull the information of the active view. There are a few views in the system that has tabs. For those pages, we’d like to get the page title as well as the tab titel, to better understand which tab the user is on. So instead of getting “Setup - Payments” we can get “Setup - Payments - Payment Gateway” as the name of the current page (and tab).

Again thanks for your feedback!