Show page title in layout

Hello Vaadin community,

how can I access the page title of the currently routed content in its layout class (e.g. for showing it in a global headline section) ?

Thank you.

You have two alternatives. Either you can use @PageTitle(“My title”) annotation with the view (i.e. route), or alternatively you can implement HasDynamicTitle in your view class and return the title in getPageTitle() method, see more here: https://vaadin.com/docs/v13/flow/routing/tutorial-routing-page-titles.html

Thank you for your answer, Tatu.

It explains how to set the title from within the routed class.

But how can I read the current page title from the layout class?

Example:

@PageTitle("Section A")
@Route(value = "section_a", layout = MainLayout.class)
public class ViewA extends Div {
	// ...
}

@PageTitle("Section B")
@Route(value = "section_b", layout = MainLayout.class)
public class ViewB extends Div {
	// ...
}


public class MainLayout extends Div implements RouterLayout {
	public MainLayout() {
		// Navigation:
		add(new RouterLink("To Section A", ViewA.class);
		add(new RouterLink("To Section B", ViewB.class);
		
		
		// Top Bar:
		Element headline = new Element("h1");
        headline.setText(/* Get current page title here ? */);
        getElement().appendChild(headline); 
		
		// ...
	}
}

You can get it with a callback, at least.

public class MainView extends VerticalLayout implements HasDynamicTitle {

    private static int i = 0;

    @Override
    public String getPageTitle() {
        return (++i) + " dynamic title";
    }

    public MainView() {
        this.getElement().executeJavaScript("this.$server.show(document.title)");

    }

    @ClientCallable
    public void show(String title) {
        add(new Span(title));
    }
}

Ok, thanks, this can be one option.

If I understand right, on server-side, there is currently no way to directly access the instance of the currently routed view class from its layout class (or vice-versa) ?

That’s right. You can of course use HasDynamicTitle and call getPageTitle(), or use Java reflection to find what the @PageTitle annotation holds, but that’s not guaranteed to be up to date with the client side.

I still don’t quite get it :smiley:

getPageTitle() is not a static method… How could I call it, when I don’t have the class instance?

Good point! I think reflection and reading the annotation’s value would be the way, then. Or you could store the value used in the annotation in a public static final String field:

@PageTitle(MainView.TITLE)
public class MainView extends VerticalLayout {

    public static final String TITLE = "Something";

After some more testing I might have found a suitable solution for the problem.

The instance of the routed class is passed to the Layout as the ‘hasElement’ parameter of the showRouterLayoutContent-Method.

This way you can gather the page title using reflections:

public class MainLayout extends Div implements RouterLayout {
	
	private Element mHeadline = new Element("h1");

	public MainLayout() {
		// ...
		
		// attach headline somewhere in your layout:
        getElement().appendChild(mHeadline); 
		
		// ...
	}
	
	@Override
    public void showRouterLayoutContent(HasElement hasElement) {
		super(); // or use own implementation to attach hasElement to current layout 
		
		// read page title from annotation of routed class
        String title = hasElement.getClass().getAnnotationsByType(PageTitle.class)[0]
.value();
        
		// update headline element
		mHeadline.setText(title);
    }
	
}

You could also do an instanceof comparism and cast the hasElement to the corresponding class or its interfaces to have full interaction with the routed object.

Looks good! You might want to add some sanity check there, in case you forget to put the @PageTitle annotation on some route, for example.