Using Navigator for creating bookmarkable applications with back-forward button support

Vaadin 7 has introduced a new capability for easy creation of bookmarkable applications with back and forward button support: the Navigator.

We will see how to use the Navigator class and what is needed to get it working. Navigator works with views, layouts that implement the View interface.

We are going to make an application with two views. We will be able to navigate between these two views with the back and forward buttons or make a bookmark.

The first view will be the welcome view, which we map to an empty URL fragment, so it becomes accessible at http://localhost:8080 address.

Using Navigator for creating bookmarkable applications with back-forward button support

When a user clicks on the Open new Orders button, the orders view is displayed with the orders URL fragment.

Using Navigator for creating bookmarkable applications with back-forward button support

How to do it...

Carry out the following steps to learn how to work with Views in Vaadin 7:

  1. Create a new Vaadin project with the main UI class called, for example, MyVaadinUI.
  2. Create the welcome view that will show a flattering label with the greeting Welcome back handsome.
    public class WelcomeView extends VerticalLayout implements View {
    
      public static final String VIEW_NAME = "";
    
      public WelcomeView() {
        Label lblWelcome = new Label("Welcome back handsome.");
        addComponent(lblWelcome);
    
        Button btnOrders = new Button("Open new Orders");
        btnOrders.addClickListener(new Button.ClickListener() {
          @Override
          public void buttonClick(Button.ClickEvent clickEvent) {
            UI ui = UI.getCurrent();
            Navigator navigator = ui.getNavigator();
            navigator.navigateTo(OrdersView.VIEW_NAME);
          }
        });
        addComponent(btnOrders);
      }
    
      @Override
      public void enter(ViewChangeListener.ViewChangeEvent event){
      }
    }
  3. Create a new view for orders and also, place there a label, which indicates we are browsing the orders.
    public class OrdersView extends VerticalLayout implements View {
    
      public static final String VIEW_NAME = "orders";
    
      public OrdersView() {
        Label lblOrders = new Label("New orders: ");
        addComponent(lblOrders);
      }
    
      @Override
      public void enter(ViewChangeListener.ViewChangeEvent event) {
        // for example: load / reload data from database
      }
    }
  4. Create a new UI class and set up the navigator.
    public class MyVaadinUI extends UI {
    
      @Override
      protected void init(VaadinRequest request) {
        Navigator navigator = new Navigator(this, this);
    
        navigator.addView(WelcomeView.VIEW_NAME, new WelcomeView());
        navigator.addView(OrdersView.VIEW_NAME, OrdersView.class);
    
        navigator.navigateTo(WelcomeView.VIEW_NAME);
      }
    }
  5. Run the application and click on the Open new Orders button. Orders view appears and when we click on the back button in the browser, we will be returned to the welcome view.

How it works...

We have made a new instance of Navigator in the init method. Then we have added two views into the navigator and we have commanded the navigator to navigate to WelcomeView.

The first view has been added as a new instance of the WelcomeView class. That way, we ensure there will be only one instance of the WelcomeView class created for all navigation events.

navigator.addView(WelcomeView.VIEW_NAME, new WelcomeView());

The second view has been initialized via the OrdersView class. Setting a class instead of an instance is the opposite approach to setting an instance of a view to the navigator. Because when we add a class as a view to the navigator, a new instance of the view class is created for each navigation event.

navigator.addView(OrdersView.VIEW_NAME, OrdersView.class);

Both Welcome and Orders views are created as layouts that implement the View interface and contain a static field VIEW_NAME that defines the name of the view that is going to be set as a fragment into the URI.

When a view is being opened, the enter method is called. For example, we could fetch data from the database in the enter method, instead of fetching data in the constructor. The reasoning why we don't touch the database in a constructor is that, when we have tied I/O operations with the constructor, the class will become difficult to test.

There's more...

We can pass additional parameters into the view. We just extend the link with additional parameters, for example, http://localhost:8080/#!order/detail/1.

Then we get the parameters in the enter method. The parameters variable contains detail/1 string from the previous example.

public void enter(ViewChangeListener.ViewChangeEvent event) {
  String parameters = event.getParameters();
  addComponent(new Label(parameters));