You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

advanced-navigator.asciidoc 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. ---
  2. title: Navigating in an Application
  3. order: 9
  4. layout: page
  5. ---
  6. [[advanced.navigator]]
  7. = Navigating in an Application
  8. Plain Vaadin applications do not have normal web page navigation as they usually
  9. run on a single page, as all Ajax applications do. Quite commonly, however,
  10. applications have different views between which the user should be able to
  11. navigate. The [classname]#Navigator# in Vaadin can be used for most cases of
  12. navigation. Views managed by the navigator automatically get a distinct URI
  13. fragment, which can be used to be able to bookmark the views and their states
  14. and to go back and forward in the browser history.
  15. [[advanced.navigator.navigating]]
  16. == Setting Up for Navigation
  17. The [classname]#Navigator# class manages a collection of __views__ that
  18. implement the [interfacename]#View# interface. The views can be either
  19. registered beforehand or acquired from a __view provider__. When registering,
  20. the views must have a name identifier and be added to a navigator with
  21. [methodname]#addView()#. You can register new views at any point. Once
  22. registered, you can navigate to them with [methodname]#navigateTo()#.
  23. [classname]#Navigator# manages navigation in a component container, which can be
  24. either a [interfacename]#ComponentContainer# (most layouts) or a
  25. [interfacename]#SingleComponentContainer# ( [classname]#UI#, [classname]#Panel#,
  26. or [classname]#Window#). The component container is managed through a
  27. [interfacename]#ViewDisplay#. Two view displays are defined:
  28. [classname]#ComponentContainerViewDisplay# and
  29. [classname]#SingleComponentContainerViewDisplay#, for the respective component
  30. container types. Normally, you can let the navigator create the view display
  31. internally, as we do in the example below, but you can also create it yourself
  32. to customize it.
  33. Let us consider the following UI with two views: start and main. Here, we define
  34. their names with enums to be typesafe. We manage the navigation with the UI
  35. class itself, which is a [interfacename]#SingleComponentContainer#.
  36. [source, java]
  37. ----
  38. public class NavigatorUI extends UI {
  39. Navigator navigator;
  40. protected static final String MAINVIEW = "main";
  41. @Override
  42. protected void init(VaadinRequest request) {
  43. getPage().setTitle("Navigation Example");
  44. // Create a navigator to control the views
  45. navigator = new Navigator(this, this);
  46. // Create and register the views
  47. navigator.addView("", new StartView());
  48. navigator.addView(MAINVIEW, new MainView());
  49. }
  50. }
  51. ----
  52. See the http://demo.vaadin.com/book-examples-vaadin7/book#advanced.navigator.basic[on-line example, window="_blank"].
  53. The [classname]#Navigator# automatically sets the URI fragment of the
  54. application URL. It also registers a [interfacename]#URIFragmentChangedListener#
  55. in the page
  56. ifdef::web[]
  57. (see <<dummy/../../../framework/advanced/advanced-urifu#advanced.urifu,"Managing
  58. URI
  59. Fragments">>)
  60. endif::web[]
  61. to show the view identified by the URI fragment if entered or navigated to in
  62. the browser. This also enables browser navigation history in the application.
  63. [[advanced.navigator.navigating.viewprovider]]
  64. === View Providers
  65. You can create new views dynamically using a __view provider__ that implements
  66. the [interfacename]#ViewProvider# interface. A provider is registered in
  67. [classname]#Navigator# with [methodname]#addProvider()#.
  68. The [methodname]#ClassBasedViewProvider# is a view provider that can dynamically
  69. create new instances of a specified view class based on the view name.
  70. The [methodname]#StaticViewProvider# returns an existing view instance based on
  71. the view name. The [methodname]#addView()# in [classname]#Navigator# is actually
  72. just a shorthand for creating a static view provider for each registered view.
  73. [[advanced.navigator.navigating.viewchangelistener]]
  74. === View Change Listeners
  75. You can handle view changes also by implementing a
  76. [interfacename]#ViewChangeListener# and adding it to a [classname]#Navigator#.
  77. When a view change occurs, a listener receives a [classname]#ViewChangeEvent#
  78. object, which has references to the old and the activated view, the name of the
  79. activated view, as well as the fragment parameters.
  80. [[advanced.navigator.view]]
  81. == Implementing a View
  82. Views can be any objects that implement the [interfacename]#View# interface.
  83. When the [methodname]#navigateTo()# is called for the navigator, or the
  84. application is opened with the URI fragment associated with the view, the
  85. navigator switches to the view and calls its [methodname]#enter()# method.
  86. To continue with the example, consider the following simple start view that just
  87. lets the user to navigate to the main view. It only pops up a notification when
  88. the user navigates to it and displays the navigation button.
  89. [source, java]
  90. ----
  91. /** A start view for navigating to the main view */
  92. public class StartView extends VerticalLayout implements View {
  93. public StartView() {
  94. setSizeFull();
  95. Button button = new Button("Go to Main View",
  96. new Button.ClickListener() {
  97. @Override
  98. public void buttonClick(ClickEvent event) {
  99. navigator.navigateTo(MAINVIEW);
  100. }
  101. });
  102. addComponent(button);
  103. setComponentAlignment(button, Alignment.MIDDLE_CENTER);
  104. }
  105. @Override
  106. public void enter(ViewChangeEvent event) {
  107. Notification.show("Welcome to the Animal Farm");
  108. }
  109. }
  110. ----
  111. See the http://demo.vaadin.com/book-examples-vaadin7/book#advanced.navigator.basic[on-line example, window="_blank"].
  112. You can initialize the view content in the constructor, as was done in the
  113. example above, or in the [methodname]#enter()# method. The advantage with the
  114. latter method is that the view is attached to the view container as well as to
  115. the UI at that time, which is not the case in the constructor.
  116. [[advanced.navigator.urifragment]]
  117. == Handling URI Fragment Path
  118. URI fragment part of a URL is the part after a hash [literal]#++#++# character.
  119. Is used for within-UI URLs, because it is the only part of the URL that can be
  120. changed with JavaScript from within a page without reloading the page. The URLs
  121. with URI fragments can be used for hyperlinking and bookmarking, as well as
  122. browser history, just like any other URLs. In addition, an exclamation mark
  123. [literal]#++#!++# after the hash marks that the page is a stateful AJAX page,
  124. which can be crawled by search engines. Crawling requires that the application
  125. also responds to special URLs to get the searchable content. URI fragments are
  126. managed by [classname]#Page#, which provides a low-level API.
  127. URI fragments can be used with [classname]#Navigator# in two ways: for
  128. navigating to a view and to a state within a view. The URI fragment accepted by
  129. [methodname]#navigateTo()# can have the view name at the root, followed by
  130. fragment parameters after a slash (" [literal]#++/++#"). These parameters are
  131. passed to the [methodname]#enter()# method in the [interfacename]#View#.
  132. In the following example, we implement within-view navigation. Here we use the
  133. following declarative design for the view:
  134. [source, html]
  135. ----
  136. <vaadin-vertical-layout size-full>
  137. <vaadin-horizontal-layout size-full :expand>
  138. <vaadin-panel caption="List of Equals" height-full width-auto>
  139. <vaadin-vertical-layout _id="menuContent" width-auto margin/>
  140. </vaadin-panel>
  141. <vaadin-panel _id="equalPanel" caption="An Equal" size-full :expand/>
  142. </vaadin-horizontal-layout>
  143. <vaadin-button _id="logout">Logout</vaadin-button>
  144. </vaadin-vertical-layout>
  145. ----
  146. The view's logic code would be as follows:
  147. [source, java]
  148. ----
  149. /** Main view with a menu (with declarative layout design) */
  150. @DesignRoot
  151. public class MainView extends VerticalLayout implements View {
  152. // Menu navigation button listener
  153. class ButtonListener implements Button.ClickListener {
  154. String menuitem;
  155. public ButtonListener(String menuitem) {
  156. this.menuitem = menuitem;
  157. }
  158. @Override
  159. public void buttonClick(ClickEvent event) {
  160. // Navigate to a specific state
  161. navigator.navigateTo(MAINVIEW + "/" + menuitem);
  162. }
  163. }
  164. VerticalLayout menuContent;
  165. Panel equalPanel;
  166. Button logout;
  167. public MainView() {
  168. Design.read(this);
  169. menuContent.addComponent(new Button("Pig",
  170. new ButtonListener("pig")));
  171. menuContent.addComponent(new Button("Cat",
  172. new ButtonListener("cat")));
  173. menuContent.addComponent(new Button("Dog",
  174. new ButtonListener("dog")));
  175. menuContent.addComponent(new Button("Reindeer",
  176. new ButtonListener("reindeer")));
  177. menuContent.addComponent(new Button("Penguin",
  178. new ButtonListener("penguin")));
  179. menuContent.addComponent(new Button("Sheep",
  180. new ButtonListener("sheep")));
  181. // Allow going back to the start
  182. logout.addClickListener(event -> // Java 8
  183. navigator.navigateTo(""));
  184. }
  185. @DesignRoot
  186. class AnimalViewer extends VerticalLayout {
  187. Label watching;
  188. Embedded pic;
  189. Label back;
  190. public AnimalViewer(String animal) {
  191. Design.read(this);
  192. watching.setValue("You are currently watching a " +
  193. animal);
  194. pic.setSource(new ThemeResource(
  195. "img/" + animal + "-128px.png"));
  196. back.setValue("and " + animal +
  197. " is watching you back");
  198. }
  199. }
  200. @Override
  201. public void enter(ViewChangeEvent event) {
  202. if (event.getParameters() == null
  203. || event.getParameters().isEmpty()) {
  204. equalPanel.setContent(
  205. new Label("Nothing to see here, " +
  206. "just pass along."));
  207. return;
  208. } else
  209. equalPanel.setContent(new AnimalViewer(
  210. event.getParameters()));
  211. }
  212. }
  213. ----
  214. See the http://demo.vaadin.com/book-examples-vaadin7/book#advanced.navigator.basic[on-line example, window="_blank"].
  215. The animal sub-view would have the following declarative design:
  216. [source, html]
  217. ----
  218. <vaadin-vertical-layout size-full>
  219. <vaadin-label _id="watching" size-auto :middle :center/>
  220. <vaadin-embedded _id="pic" :middle :center :expand/>
  221. <vaadin-label _id="back" size-auto :middle :center/>
  222. </vaadin-vertical-layout>
  223. ----
  224. See the http://demo.vaadin.com/book-examples-vaadin7/book#advanced.navigator.basic[on-line example, window="_blank"].
  225. The main view is shown in <<figure.advanced.navigator.mainview>>. At this point,
  226. the URL would be [literal]#++http://localhost:8080/myapp#!main/reindeer++#.
  227. [[figure.advanced.navigator.mainview]]
  228. .Navigator Main View
  229. image::img/navigator-mainview.png[]