From cca89c574379d350fa0715a42eceb988b5c8b3f5 Mon Sep 17 00:00:00 2001 From: Erik Lumme Date: Wed, 13 Sep 2017 14:42:03 +0300 Subject: [PATCH] Migrate CreatingABookmarkableApplicationWithBackButtonSupport --- ...eApplicationWithBackButtonSupport.asciidoc | 140 ++++++++++++++++++ documentation/articles/contents.asciidoc | 1 + 2 files changed, 141 insertions(+) create mode 100644 documentation/articles/CreatingABookmarkableApplicationWithBackButtonSupport.asciidoc diff --git a/documentation/articles/CreatingABookmarkableApplicationWithBackButtonSupport.asciidoc b/documentation/articles/CreatingABookmarkableApplicationWithBackButtonSupport.asciidoc new file mode 100644 index 0000000000..e01ea78bc7 --- /dev/null +++ b/documentation/articles/CreatingABookmarkableApplicationWithBackButtonSupport.asciidoc @@ -0,0 +1,140 @@ +[[creating-a-bookmarkable-application-with-back-button-support]] +Creating a bookmarkable application with back button support +------------------------------------------------------------ + +Vaadin 7 comes with a new set of APIs to aid creation of navigation +within your application. The main concepts are *Navigator* and *View*, +and using these you can easily create an application that supports the +standard browser methods for navigation; bookmarking, history, back- and +forward navigation using browser buttons. This is (usually) done using +browser "fragments" (the stuff after the #-character in the URI). + +At the same time, the API provides a natural way of partitioning your +application into views - something most applications did previously +anyway, but previously without framework 'guidance'. + +Let's start by making a View that counts the times it has been created. +This is a simple example, but will later shed some light on when Views +are created, but let's not worry about that just yet: + +[source,java] +.... +import com.vaadin.navigator.View; +import com.vaadin.ui.Label; +import com.vaadin.ui.Panel; + +public class CountView extends Panel implements View { + public static final String NAME = "count"; + + private static int count = 1; + + public CountView() { + setContent(new Label("Created: " + count++)); + } + + public void enter(ViewChangeEvent event) { + } +} +.... + +We'll extend Panel as a convenient base, and add a Label to that in the +constructor, updating the static count. The _enter()_ -method comes from +View, and is called when our View is activated, but we'll do nothing +about that in our simplistic View. + +Note the _static final NAME_: we'll use it instead of a 'magic' string +when we register the View with the Navigator later. Feel free to use any +method you like to keep track of your View-names (e.g Enum, simpleName +of the View's class, and so on…) + +In order to do any navigating, we'll need at least two views, so let's +create a main view that has a link to the counting view we just created. + +[source,java] +.... +import com.vaadin.navigator.View; +import com.vaadin.server.ExternalResource; +import com.vaadin.ui.Link; +import com.vaadin.ui.Panel; + +public class MainView extends Panel implements View { + + public static final String NAME = ""; + + public MainView() { + Link lnk = new Link("Count", new ExternalResource("#!" + + CountView.NAME)); + setContent(lnk); + } + + public void enter(ViewChangeEvent event) { + } +} +.... + +Note the empty string used as _NAME_. This is because we want this to be +our main ("home") View, displayed before any navigation is done. + +In this example we use a Link and let the browser do the navigating. We +could just as easily use a Button and tell the Navigator where we want +to go when the button's ClickListener is invoked. Note that we're using +_CountView.NAME_, and what we're actually doing is using the "fragment" +part of the application URI to indicate the view. The resulting URI will +look something like http://.../application#count . + +Ok, one last thing: we need to set up a UI with a Navigator, and +register our views: + +[source,java] +.... +import com.vaadin.navigator.Navigator; +import com.vaadin.navigator.Navigator.SimpleViewDisplay; +import com.vaadin.server.Page; +import com.vaadin.server.WrappedRequest; +import com.vaadin.ui.UI; + +public class NavigationtestUI extends UI { + @Override + public void init(VaadinRequest request) { + // Create Navigator, use the UI content layout to display the views + Navigator navigator = new Navigator(this, this); + + // Add some Views + navigator.addView(MainView.NAME, new MainView()); // no fragment + + // #count will be a new instance each time we navigate to it, counts: + navigator.addView(CountView.NAME, CountView.class); + + // The Navigator attached to the UI will automatically navigate to the initial fragment once + // the UI has been initialized. + } +} +.... + +There are advanced ways to use the Navigator API, and there are simple +ways. Most applications will do fine with the simple ways, and the +Navigator constructor we used is written that in mind. It simply takes +any ComponentContainer, assumes that all our Views are also Components, +and on a view change sets the given view as the ComponentContainer's +only child. Internally, it uses a _ViewDisplay_ subclass called +ComponentContainerViewDisplay to do this. If we had more advanced +requirements, we could write our own ViewDisplay subclass to show our +views in whatever fashion we'd like. + +The Navigator finds out about URI fragment changes through the Page, and +directs the ViewDisplay accordingly. We register our Views using +_addView()_ so that the Navigator knows how to connect fragments with +Views. Again notice how we use the static NAME instead of +_addView("name", view)_ - but feel free to use other approaches. + +In order to illustrate how the two differ, we register an _instance_ of +the MainView, but _CountView.class_. As a result, the MainView is +created once, when the UI is created, and lives as long as the UI lives. +On the other hand, a new CountView instance will be created each time we +navigate to it (but no earlier). You can try navigating back-and-forth +and see how the count is updated - try registering it using new +CountView() instead… + +It's also good to keep in mind that a new UI is created each time you +press reload in the browser, unless you use the @PreserveOnRefresh +annotation on the UI. diff --git a/documentation/articles/contents.asciidoc b/documentation/articles/contents.asciidoc index d3ef0c9a32..ee59f2b632 100644 --- a/documentation/articles/contents.asciidoc +++ b/documentation/articles/contents.asciidoc @@ -87,3 +87,4 @@ are great, too. - link:CreatingAThemeUsingSass.asciidoc[Creating a theme using Sass] - link:OpeningAUIInAPopupWindow.asciidoc[Opening a UI in a popup window] - link:ViewChangeConfirmations.asciidoc[View change confirmations] +- link:CreatingABookmarkableApplicationWithBackButtonSupport.asciidoc[Creating a bookmarkable application with back button support] -- 2.39.5