Modifying the bootstrap page
The application bootstrap page is created for you by the framework and normally there is no need to modify it.
For instance Flow includes its internal JavaScripts to be able to provide its core functionality.
Also it is possible to include additional JavaScripts, HTML imports and Style Sheets using annotations @JavaScript
,
@CssImport
and @StyleSheet
(see Importing Style Sheets and Importing JavaScript).
Sometimes you may want to customize the page header and add there some additional data, e.g. custom meta
tags.
Such markup is required to enable your web page to become a rich object in a social graph using OpenGraph protocol.
Viewport annotation
Viewport meta-tag can be set to the initial page by annotating the navigation target with @Route
or
the top most RouterLayout
that builds the navigation target chain.
@Route("")
@Viewport("width=device-width")
public class MyApp extends Div {
public MyApp() {
setText("Hello world");
}
}
@Route(value = "", layout = MyLayout.class)
public class MyView extends Div {
public MyView() {
setText("Hello world");
}
}
@Viewport("width=device-width")
public class MyLayout extends Div implements RouterLayout {
}
Note
|
If the Viewport annotation is not on a `@Route Component or a top RouterLayout an exception will be thrown on startup.
|
Inline annotation
The initial page can be modified by using the @Inline
annotations to add file contents
to either the <head>
or the <body>
. Inline is repeatable, so multiple @Inline
annotations
can be added at once.
Inline will add the contents of a classloader resource by default as appended to the head of the initial page with type decided by the file suffix.
The configurations available for inlining contents are:
-
TargetElement [HEAD, BODY]
-
Position [APPEND, PREPEND]
-
Wrapping [AUTOMATIC, NONE, STYLESHEET, JAVASCRIPT]
@Route(value = "", layout = MyInline.class)
public class MyRoot extends Div {
public MyRoot() {
}
}
@Inline("initialization.js")
@Inline("initial_style.css")
@Inline(value = "important_styles", wrapping = Inline.Wrapping.STYLESHEET)
public class MyInline extends Div implements RouterLayout {
}
Note
|
If the Inline annotation is not on a @Route Component or a top RouterLayout an exception will be thrown on startup.
|
PageConfigurator
To be able to modify default bootstrap page and add your custom meta tags on the page you
can implement the PageConfigurator
on the navigation target with @Route
or
the top most RouterLayout
that builds the navigation target chain. The PageConfigurator
gives
you easy access to customize the LoadingIndicatorConfiguration
, ReconnectDialogConfiguration
and
PushConfiguration
for the initial response.
With the PageConfigurator
you can prepend or append javascript
, html
and css
to the head
by giving a file on the classpath or as content string. Also supported is adding links and meta tags which
can also be either prepended or appended.
Setting the viewport meta tag using InitialPageSettings::setViewport
will override any viewport
set through a @Viewport
annotation.
By default everything is appended, but if needed you can give the position InitialPageSettings.Position.PREPEND
to have the item prepended to head instead.
Here is the code for the PageConfigurator
implementation on the top
RouterLayout
which modifies the header of the page:
@Route(value = "", layout = MainLayout.class)
public class Root extends Div {
}
public class MainLayout extends Div
implements RouterLayout, PageConfigurator {
@Override
public void configurePage(InitialPageSettings settings) {
settings.addInlineFromFile(InitialPageSettings.Position.PREPEND,
"inline.js", InitialPageSettings.WrapMode.JAVASCRIPT);
settings.addMetaTag("og:title", "The Rock");
settings.addMetaTag("og:type", "video.movie");
settings.addMetaTag("og:url",
"https://www.imdb.com/title/tt0117500/");
settings.addMetaTag("og:image",
"https://ia.media-imdb.com/images/rock.jpg");
settings.addLink("shortcut icon", "icons/favicon.ico");
settings.addFavIcon("icon", "icons/icon-192.png", "192x192");
}
}
Note
|
If the PageConfigurator implementation is not on a @Route Component or a RouterLayout used from a route it will not be used.
|
Setting the body size styles
By default, the body element in a Flow application has size properties height = "100vh", width = "100vw"
,
which makes the page fill the entire viewport.
To change the width and height properties of the body you can either use the @BodySize
annotation or the PageConfigurator
.
For @BodySize
you just add it to the the navigation target with @Route
or
the top most RouterLayout
that builds the navigation target chain.
You can pass custom height and width properties for the annotation, or leave them out
to just prevent the default size to be applied for the body:
@Route("")
@BodySize
public static class BodySizeAnnotatedRoute extends Div {
}
With the PageConfigurator
you can just addInlineContent like:
@Route("")
public static class InitialPageConfiguratorBodyStyle extends Div
implements PageConfigurator {
@Override
public void configurePage(InitialPageSettings settings) {
settings.addInlineWithContents("body {width: 100vw; height:100vh;}",
InitialPageSettings.WrapMode.STYLESHEET);
}
}
Note
|
Only one way should be used as else the later statement will override the earlier one. In practise this would
mean that by default the PageConfigurator will override the @BodySize except if the inlining is done as
a PREPEND then the @BodySize will be the deciding one.
|
Note
|
If the BodySize annotation is not on a @Route Component or a top RouterLayout an exception will be thrown on startup.
|
Note
|
When using an empty @BodySize annotation (which doesn’t apply any sizing for the UI / body), you will not be able to use relative sizing (% as unit) for any component, unless the component has a parent that has defined size using anything else than % as the unit. For that reason, it is recommended to use the default settings for the body size, by omitting the @BodySize annotation, or to declare a specific size for it.
|
BootstrapListener
To be able to modify default bootstrap page and add your custom meta tags on the page you should use
your BootstrapListener
implementation and add it to the ServiceInitEvent
instance available
in a VaadinServiceInitListener
.
Here is the code for the BoostrapListener
implementation which modifies the header of the page:
public class CustomBootstrapListener implements BootstrapListener {
public void modifyBootstrapPage(BootstrapPageResponse response) {
Document document = response.getDocument();
Element head = document.head();
head.appendChild(createMeta(document, "og:title", "The Rock"));
head.appendChild(createMeta(document, "og:type", "video.movie"));
head.appendChild(createMeta(document, "og:url",
"https://www.imdb.com/title/tt0117500/"));
head.appendChild(createMeta(document, "og:image",
"https://ia.media-imdb.com/images/rock.jpg"));
}
private Element createMeta(Document document, String property,
String content) {
Element meta = document.createElement("meta");
meta.attr("property", property);
meta.attr("content", content);
return meta;
}
}
Now this listener should be added to a ServiceInitEvent
which is sent when a Vaadin service is initialized. Take a look on the ServiceInitListener tutorial on how to configure it.
Adding static HTML contents
The framework provides multiple ways of adding static content to the page. Here we cover three different ways of adding a favicon.
-
using
InitialPageSettings#addLink()
public class Layout1 extends Div implements RouterLayout, PageConfigurator {
@Override
public void configurePage(InitialPageSettings settings) {
HashMap<String, String> attributes = new HashMap<>();
attributes.put("rel", "shortcut icon");
settings.addLink("icons/favicon.ico", attributes);
}
}
-
using
InitialPageSettings#addInlineWithContents()
public class Layout2 extends Div implements RouterLayout, PageConfigurator {
@Override
public void configurePage(InitialPageSettings settings) {
settings.addInlineWithContents(
"<link rel=\"shortcut icon\" href=\"icons/favicon.ico\">",
InitialPageSettings.WrapMode.NONE);
}
}
-
using
BootstrapListener#modifyBootstrapPage()
(documentation)
public class Layout3 extends Div
implements RouterLayout, BootstrapListener {
@Override
public void modifyBootstrapPage(BootstrapPageResponse response) {
final Element head = response.getDocument().head();
head.append(
"<link rel=\"shortcut icon\" href=\"icons/favicon.ico\">");
}
}
But most commonly, you will deal with quite many files, in this case, you can see that it causes a lot of hard coding easily. To avoid this, we recommend you to move all the contents into a file, (e.g. your-content.html
) and inline this file in your PageConfigurator
public class Layout4 extends Div implements RouterLayout, PageConfigurator {
@Override
public void configurePage(InitialPageSettings settings) {
settings.addInlineFromFile("your-content.html",
InitialPageSettings.WrapMode.NONE);
}
}
7B97DE3E-DE54-4C2D-81F4-976965D96337