12

I currently try to set the title of the page.


Scenario

public class A extends FlexLayout implements RouterLayout {}

@Route(value = "b", layout = A.class)
public class B extends FlexLayout{}
@Route(value = "c", layout = A.class)
public class C extends FlexLayout{}

Attempts

  1. To do so I tried to call UI.getCurrent().getPage().setTitle("demo title") during afterNavigation. Unfortunately this does not work for the initial navigation (and neither worked adding an attachListener).

  2. I also tried configuring it using the PageConfigurator on the outermost RouterLayout like this:

    @Override
    public void configurePage(InitialPageSettings settings) {
        settings.addMetaTag("title", "demo title");
        settings.addMetaTag("og:title", "demo title");

        settings.addFavIcon("icon", "frontend/images/favicon.ico", "48x48");
    }
  1. HasDynamicTitle only seems to work if the implementing class also defines the @Route but not the encapsulating RouterLayout

Issue

For some reason the Router itself sets the title during navigation.

Stacktrace of the setTitleCall

The Router defines the title using JS and redefining document.title while Page.setTitle seems to only modify the html.head.title tag.


Question

How does one set the title in a single spot?
How does one prevent the Router form setting the title to the value of the current URL?


Note

Using the @PageTitle annotation is not an option as in my case the title is not known at compiletime.

Gerrit Sedlaczek
  • 1,231
  • 1
  • 14
  • 32
  • Could you try to call this `UI.getCurrent().getPage().executeJavaScript("document.title = $0",your_title);` in your `attachListener`? And if this doesn't work then implement the `BeforeEnterObserver` and call it inside `beforeEnter`. But a `HasDynamicTitle ` should work based on the documentation. So might be a bug :/ – anasmi May 10 '19 at 16:16
  • 1
    Thank you for replying. I guess Ill try to add a JS changelistener during UI init. But thats a dirty hack imo. – Gerrit Sedlaczek May 13 '19 at 08:13
  • 1
    I ended up setting the title by creating an interface that implements `HasDynamicTitle` and adding that interface to each and every `Route` endpoint. – Gerrit Sedlaczek May 16 '19 at 08:49
  • I dont consider this workaround a solution as it creates the possibilty for inconsistant title because someone who adds a new `Route` has to know / remember that setting the interface is required. – Gerrit Sedlaczek May 22 '19 at 15:42

1 Answers1

3

Fixed title

If you have an unchanging page title you can just set it with an annotation @PageTitle.

@PageTitle("home")
class HomeView extends Div {

  HomeView(){
    setText("This is the home view");
  }
}

Dynamic title

The official Vaadin Flow documentation suggests to use the HasDynamicTitle.

Example:

@Route(value = "blog")
class BlogPost extends implements HasDynamicTitle, HasUrlParameter<Long> {
  private String title = "";

  @Override
  public String getPageTitle() {
    return title;
  }

  @Override
  public void setParameter(BeforeEvent event,
        @OptionalParameter Long parameter) {
    if (parameter != null) {
      title = "Blog Post #" + parameter;
    } else {
      title = "Blog Home";
    }
  }
}

Source

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
LOLWTFasdasd asdad
  • 2,625
  • 5
  • 26
  • 39
  • As I pointed out in Attempt#3 using the `HasDynamicTitle`works fine but is redundant. My scenario involves a single parent that has a lot of children with different routes. I would like to define the `title` once in that parent layout (a `RouterLayout`) like `PageTitle` would allow you to. – Gerrit Sedlaczek May 22 '19 at 14:54
  • By childen do you mean they are programmatically extending the mother component? So you want to avoid that every child has to implement the interface but setting each route for each child dynamically? – LOLWTFasdasd asdad May 22 '19 at 15:04
  • No unfortunately not. In that case `HasDynamicTitle` would work. I my case I have a lot of classes with `Route`annotations. These annotations reference a common `RouterLayout` by using the `layout` property. – Gerrit Sedlaczek May 22 '19 at 15:29
  • I added a scenario section for clarification. – Gerrit Sedlaczek May 22 '19 at 15:37
  • I think there is no other way except you did. If I understood you right this was once considered a possible solution for your problem but got scrapped: https://github.com/vaadin/flow/issues/4802 – LOLWTFasdasd asdad May 22 '19 at 16:27