Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Examples for MultiSelectComboBox Features (PR 2963) #3010

Merged
merged 4 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 39 additions & 58 deletions articles/advanced/modifying-the-bootstrap-page.adoc
Original file line number Diff line number Diff line change
@@ -1,50 +1,40 @@
---
title: Modifying the Bootstrap Page at Runtime
description: How to customize the application shell, or bootstrap page, to improve page loading speed.
title: Modifying Bootstrap Page at Runtime
description: Customizing an application shell (a.k.a., bootstrap page) to improve page loading speed.
order: 30
---


= Modifying the Bootstrap Page at Runtime
= Modifying Bootstrap Page at Runtime

== Application Shell [[application-shell]]
The link:https://developers.google.com/web/fundamentals/architecture/app-shell[application shell model] aims to make websites faster by loading the _important_ parts of web pages first to improve the user experience. The key to this is to deliver the minimum HTML, CSS and JavaScript required to display the user interface on the first visit, and to cache it for use on subsequent visits.

The link:https://developers.google.com/web/fundamentals/architecture/app-shell[application shell model] aims to make your website faster by loading the 'important' parts of the web page first, so improving the user experience. The key to this is to deliver the minimum HTML, CSS and JavaScript required to display the user interface on the first visit, and eventually cache it for use on subsequent revisits.
The _Application Shell_ in Vaadin Flow is also known as the _Bootstrap Page_, or [filename]`index.html`.

The _Application Shell_ in Vaadin is also known as the _Bootstrap Page_, or [filename]`index.html`.

== Modifying the Application Shell

In Vaadin 15 and later, the developer has full control of the contents of [filename]`index.html`.
You can modify it in various ways:
The developer has full control of the contents of [filename]`index.html`. You can modify it in various ways.

On the client side, you can edit [filename]`frontend/index.html` when the content is static, for instance the `<viewport>` tag. On the server side, you can make changes that require dynamic server content, or when Java syntax is preferred. An example of would be making the application installable by enabling the `@PWA` built-in feature.

. On the client side, by editing [filename]`frontend/index.html` when the content is static, for instance the `<viewport>` tag.
. On the server side, for changes that require some dynamic server content, or when Java syntax is preferred; for example, making the application installable by enabling the `@PWA` built-in feature.
- Implement [interfacename]`AppShellConfigurator` for cases covered by the [classname]`AppShellSettings` API, or by annotations.
- Configure an [interfacename]`IndexHtmlRequestListener` for advanced cases that modify the document structure.
You can implement [interfacename]`AppShellConfigurator` for cases covered by the [classname]`AppShellSettings` API, or by annotations. And you can configure an [interfacename]`IndexHtmlRequestListener` for advanced cases to modify the document structure.

== Customizing the Application Shell Template

The Vaadin servlet uses the [filename]`frontend/index.html` file as a template to generate the bootstrap page response.
The servlet processes the template and injects the following information:
== Application Shell Template

- `<base href='./relative/to/root'>`: Vaadin calculates the relative path from the current request path to the root path of the application.
That's required for relative links in view templates to work correctly.
The Vaadin servlet uses the [filename]`frontend/index.html` file as a template to generate the bootstrap page response. The servlet processes the template and injects the following information:

- Bundled script: Vaadin automatically adds the bundled and optimized script generated from the [filename]`frontend/index.ts` file.
It uses a pre-configured https://vitejs.dev/[Vite] instance that's included together with `vaadin-maven-plugin` as a module bundler.
Therefore, the [filename]`frontend/index.html` template doesn't need to include the [filename]`index.ts` (or [filename]`index.js`) script explicitly.
- `<base href='./relative/to/root'>`: Vaadin calculates the relative path from the current request path to the root path of the application. This is required for relative links in view templates to work correctly.
- Bundled script: Vaadin automatically adds the bundled and optimized script generated from the [filename]`frontend/index.ts` file. It uses a pre-configured https://vitejs.dev/[Vite] instance that's included with `vaadin-maven-plugin` as a module bundler. Therefore, the [filename]`frontend/index.html` template doesn't need to include explicitly the [filename]`index.ts` script -- or the [filename]`index.js` script.

.You can change the [filename]`frontend` directory path
[TIP]
The `frontend` directory path can be changed by providing the property `vaadin.frontend.frontend.folder` when running the Maven goals `prepare-frontend` or `build-frontend` from `vaadin-maven-plugin`.

=== Default Bootstrap Template and Entry Point [[default-bootstrap-template-and-entry-point]]

If the [filename]`index.html` or [filename]`index.ts` files in the frontend folder are missing, `vaadin-maven-plugin` generates a default corresponding file in the [filename]`target` folder.
In that case the application uses server-side routing only.
You can take control of these files by moving them into the [filename]`frontend` folder.
By default these files look similar to the following:
=== Default Template & Entry Point [[default-bootstrap-template-and-entry-point]]

If the [filename]`index.html` or [filename]`index.ts` files in the frontend folder are missing, `vaadin-maven-plugin` generates a default corresponding file in the [filename]`target` folder. In that case, the application uses only server-side routing. You can take control of these files by moving them into the [filename]`frontend` folder. By default, these files look similar to the following:

.Default `index.html`
[source,html]
Expand Down Expand Up @@ -90,7 +80,7 @@ const routes = [
...serverSideRoutes // IMPORTANT: this must be the last entry in the array
];

// Vaadin router needs an outlet in the index.html page to display views
// The Vaadin router needs an outlet in the index.html page to display views
export const router = new Router(document.querySelector('#outlet'));
router.setRoutes(routes);
----
Expand Down Expand Up @@ -120,35 +110,35 @@ This is the best place to customize the application shell, for example to put an
----


== Customizing the Application Shell at Runtime
== Customizing Application Shell at Runtime

=== The AppShellConfigurator Interface [[application-shell-configurator]]
You may use a few methods to customize an application shell at runtime. They're described in the following sub-sections.

In Java code, when adding dynamic content during the bootstrap process, use the [interfacename]`AppShellConfigurator` marker interface rather than editing the [filename]`index.html`.
=== `AppShellConfigurator` Interface [[application-shell-configurator]]

[NOTE]
====
There must be a single application shell for the entire Vaadin application. This way no more than one class can implement [interfacename]`AppShellConfigurator`. Incidentally, [interfacename]`AppShellConfigurator` replaced the obsolete [interfacename]`PageConfigurator` interface.
In Java code, when adding dynamic content during the bootstrap process, use the [interfacename]`AppShellConfigurator` marker interface, rather than editing the [filename]`index.html` file.

The application shell class should not extend the `Component` class, since application shells are intended only for page configuration and are instantiated before the UI is created. Currently, this check is silently ignored, but future Vaadin versions may fail with an exception in this case.
====
There must be a single application shell for the entire Vaadin application, so that no more than one class can implement [interfacename]`AppShellConfigurator`. In the case of a multi-module application, the class implementing the `AppShellConfigurator` cannot be in the dependent jar of the jar/war which starts the application.

[NOTE]
[interfacename]`AppShellConfigurator` replaces the obsolete [interfacename]`PageConfigurator` interface.


==== `AppShellConfigurator.configurePage()` Method

Override [methodname]`configurePage()` to add content to the [filename]`index.html` template by calling the following [classname]`AppShellSettings` methods:

- [methodname]`AppShellSettings.setViewport()` to set the viewport value; this replaces the viewport present in the [filename]`index.html` template.
- [methodname]`AppShellSettings.setPageTitle()` to set the initial page title; this replaces the template title tag.
- [methodname]`AppShellSettings.setViewport()` to set the viewport value. This replaces the viewport present in the [filename]`index.html` template.
- [methodname]`AppShellSettings.setPageTitle()` to set the initial page title. This replaces the template title tag.
- [methodname]`AppShellSettings.setBodySize()` to configure the body width and height values.
- [methodname]`AppShellSettings.addMetaTag()` to append meta tags to the head.
- [methodname]`AppShellSettings.addInlineFromFile()` to include content from resource files.
- [methodname]`AppShellSettings.addInlineWithContents()` to add arbitrary content.
- [methodname]`AppShellSettings.addLink()` to add links to the head.
- [methodname]`AppShellSettings.addFavIcon()` to configure the favicon.
- [methodname]`AppShellSettings.getLoadingIndicatorConfiguration()` to configure a loading indicator when legacy bootstrapping is used (deprecated; see the details after the code example).
- [methodname]`AppShellSettings.getReconnectDialogConfiguration()` to configure the reconnect dialog when legacy bootstrapping is used (deprecated; see the details after the code example).
- [methodname]`AppShellSettings.getPushConfiguration()` to customize the push mechanism when legacy bootstrapping is used (deprecated; see the details after the code example).
- [methodname]`AppShellSettings.getLoadingIndicatorConfiguration()` to configure a loading indicator when legacy bootstrapping is used. This is deprecated: see the details after the code example.
- [methodname]`AppShellSettings.getReconnectDialogConfiguration()` to configure the reconnect dialog when legacy bootstrapping is used. This is deprecated: see the details after the code example.
- [methodname]`AppShellSettings.getPushConfiguration()` to customize the push mechanism when legacy bootstrapping is used. This is deprecated: see the details after the code example.

[source,java]
----
Expand All @@ -157,7 +147,7 @@ public class AppShell implements AppShellConfigurator {
@Override
public void configurePage(AppShellSettings settings) {
settings.setViewport("width=device-width, initial-scale=1");
settings.setPageTitle("A cool vaadin app");
settings.setPageTitle("A Cool Vaadin App");
settings.setBodySize("100vw", "100vh");
settings.addMetaTag("author", "bunny");
settings.addFavIcon("icon", "icons/icon-192.png", "192x192");
Expand All @@ -174,16 +164,15 @@ public class AppShell implements AppShellConfigurator {
}
----


[source,java]
----
include::{root}/src/main/java/com/vaadin/demo/flow/advanced/bootstrap/ServiceListener.java[tags=snippet]
----


==== Java Annotations[[java-annotations]]

Vaadin provides a set of annotations to modify the application shell.
However, in Vaadin 15, unlike in previous versions, these annotations must be placed in the application shell class.
Vaadin Flow provides a set of annotations to modify the application shell.

- `@Viewport` to set the viewport value.
- `@PageTitle` to set the initial page title.
Expand All @@ -196,7 +185,7 @@ However, in Vaadin 15, unlike in previous versions, these annotations must be pl
[source,java]
----
@Viewport("width=device-width, initial-scale=1")
@PageTitle("A cool vaadin app")
@PageTitle("A Cool Vaadin App")
@BodySize(height = "100vh", width = "100vw")
@Meta(name = "author", content = "bunny")
@Inline(wrapping = Wrapping.AUTOMATIC,
Expand All @@ -209,20 +198,16 @@ public class AppShell implements AppShellConfigurator {
}
----

[NOTE]
Modifications in [methodname]`AppShellConfigurator.configurePage()` have priority over the equivalent annotations.
Modifications in [methodname]`AppShellConfigurator.configurePage()` have priority over the equivalent annotations. Annotations don't cover all of the cases that can be achieved when overriding the [methodname]`AppShellConfigurator.configurePage()` method.

[NOTE]
Annotations don't cover all the cases that can be achieved when overriding the [methodname]`AppShellConfigurator.configurePage()` method.

=== The IndexHtmlRequestListener Interface [[IndexHtmlRequestListener-interface]]
=== `IndexHtmlRequestListener` Interface [[IndexHtmlRequestListener-interface]]

For advanced cases not covered in the previous section, content can be modified via an [interfacename]`IndexHtmlRequestListener`.

An implementation of the listener should be added via a [classname]`ServiceInitEvent` when a [classname]`VaadinService` is initialized.
See the <<../advanced/service-init-listener#,ServiceInitListener tutorial>> for details of using Vaadin [classname]`ServiceInitListeners`.
An implementation of the listener should be added with a [classname]`ServiceInitEvent` when a [classname]`VaadinService` is initialized. See the <<../advanced/service-init-listener#,ServiceInitListener tutorial>> for details of using Vaadin [classname]`ServiceInitListeners`.

The following example changes the body class dynamically:
The following example changes the body class, dynamically:

[source,java]
----
Expand All @@ -245,11 +230,7 @@ public class MyIndexHtmlRequestListener implements
}
----

This can also be achieved using a servlet container deployment property with the name `useDeprecatedV14Bootstrapping`.
Note, however, that this option is only supported if webpack is used as the frontend build tool and not if the application uses Vite (which is the default).
webpack can be enabled using its associated feature flag.
Learn more about how to enable it <<{articles}/configuration/live-reload#webpack-feature-flag, here>>.

This can also be achieved using a servlet container deployment property with the name `useDeprecatedV14Bootstrapping`. Note that this option, however, is only supported if `webpack` is used as the frontend build tool and not if the application uses Vite -- which is the default. You can enable `webpack` by using its associated feature flag. Learn more about how to enable it on the <<{articles}/configuration/live-reload#webpack-feature-flag, Hot Deploy & Live Reload>> documentation page.

[discussion-id]`38A2B3F1-CC6B-45DF-8CB8-9DEF23BA53B0`

Expand Down
Loading
Loading