Navigator7
API for more web-oriented Vaadin applications
One of the goals of Vaadin 7 is (according to Joonas): "Window management should be completely revised to make supporting multi-window applications, tabbed navigation, bookmarking and web-style applications easy and logical."
I think that Navigator7 extactly addresses that.
API for more web-oriented applications.
- Notion of application level window that includes a page
- Easy navigation between pages
- Templating around pages (as header/footer/...)
- Support for fixed and fluid designs.
- Better support for multi-tab browsing.
- Rich URI analysis, with entry points for your persistency code (as JPA).
- Parameter injection (in page object's fields).
- SEO crawlable pages
- "confirm/save before leave" support
- general Interceptor (filter) mechanism
- batch jobs (needing to build URLs, i.e. for mails)
This is used in production for BlackBeltFactory.com.
This is version 7 because ... Vaadin 7 should improve to the point this addon is useless ;-) May be used to support discussion around Vaadin 7 API? [http://vaadin.com/web/joonas/wiki/-/wiki/Main/Vaadin_7_API]
Sample code
/** * In your NavigableApplication class, you define the list of pages, * and your descendent of NavigableAppLevelWindow that the application must instantiate. * * @author John Rizzo - BlackBeltFactory.com */ public class MyNavigableApplication extends NavigableApplication { // @Override // public void init() { .... // We don't override the init() method because we don't create the Window instance ourselves (the Navigator does that; and what is a Window by the way, don't wanna know about that notion: we have pages). public MyNavigableApplication() { // We need to do that in the constructor (and not later), to ensure that the init method in the ancestor has the PageTemplate and the pages. registerPages(new Class[] {Dashboard.class, Editor.class, Ticket.class, ParamTestPage.class}); setTheme("navigator7"); } @Override public NavigableAppLevelWindow createNewNavigableAppLevelWindow() { return new MyAppLevelWindow(); } }
/** Defines the template (header/footer/...) of our application level windows * * Demo of: Header/Footer templating. Note the subtle overriding of createComponents to refine the layout apprearance. * NavigationListener to get any page transition event. * Navigator.navigateTo() * * @author John Rizzo - BlackBeltFactory.com */ public class MyAppLevelWindow extends HeaderFooterFixedAppLevelWindow { @Override protected Component createHeader() { VerticalLayout header = new VerticalLayout(); header.addStyleName("header"); // Application specific style. header.setWidth("100%"); header.setHeight("100px"); ////// Hello Label l = new Label("Hello, I'm a HEADER with a menu."); l.setWidth(null); header.addComponent(l); header.setComponentAlignment(l, Alignment.TOP_RIGHT); ///// NavigationListener label final Label navLabel = new Label(); navLabel.setWidth(null); header.addComponent(navLabel); header.setComponentAlignment(navLabel, Alignment.TOP_RIGHT); getNavigator().addNavigationListener( new NavigationListener() { @Override public void pageChanged(NavigationEvent event) { navLabel.setValue("NavigationListener: pageClass = "+ event.getPageClass() + " -- params = " + event.getParams()); } }); ///// Menu MenuBar menuBar = new MenuBar(); menuBar.setWidth("100%"); header.addComponent(menuBar); header.setComponentAlignment(menuBar, Alignment.BOTTOM_LEFT); // Create one menu item with each page of the application // this is little bit artificial in the example. In a business application, you manually select (name) the pages to put in the menu, instead of having a loop. // something like: // menuBar.addItem("Manage Your Tickets", new MenuBar.Command() { // public void menuSelected(MenuItem selectedItem) { // getNavigator().navigateTo(Ticket.class); // } // }); Collection<Class <? extends Component>> pageClassColl = MyNavigableApplication.getCurrent().getNavigatorConfig().getPagesClass(); for (final Class<? extends Component> pageClass : pageClassColl) { menuBar.addItem(pageClass.getSimpleName(), new MenuBar.Command() { public void menuSelected(MenuItem selectedItem) { getNavigator().navigateTo(pageClass); } }); } return header; } @Override protected Component createFooter() { VerticalLayout vLayout = new VerticalLayout(); vLayout.setWidth("100%"); Label ll = new Label("Hello, I'm a footer!"); ll.setWidth(null); vLayout.addComponent(ll); vLayout.setComponentAlignment(ll, Alignment.TOP_CENTER); Label l = new Label("Developped by John Rizzo in 2010 for Vaadin."); l.setWidth(null); vLayout.addComponent(l); vLayout.setComponentAlignment(l, Alignment.BOTTOM_CENTER); vLayout.setHeight("200px"); return vLayout; } @Override protected ComponentContainer createComponents() { ComponentContainer result = super.createComponents(); this.getFooterBand().addStyleName("footer"); // We apply the footer to the whole outer band, not only to the fixed width inner band. return result; } }
/** * Demo of @Page, * home page concept * PageResource link * * @author John Rizzo - BlackBeltFactory.com */ @Page(uriName="dash") @SuppressWarnings("serial") public class Dashboard extends CustomComponent { GridLayout gl = new GridLayout(3, 3); public Dashboard() { // setSizeFull(); Non sense in a fixed web design (FixedPageTemplagte). VerticalLayout mainLayout = new VerticalLayout(); mainLayout.setSpacing(true); mainLayout.setSizeFull(); setCompositionRoot(mainLayout); mainLayout.addComponent( new Label("Note the uri: '#dash' instead of 'Dashboard' (page class name)." + " This is due to the @Page(uriName=\"dash\") annotation on the Dashboard class." )); mainLayout.addComponent( new Label("Dashboard is also the default home page. Try to remove the URI from the URL, e.g. http://localhost:8080/Navigator7 instead of http://localhost:8080/Navigator7#dash" )); VerticalLayout vLayout = new VerticalLayout(); vLayout.addComponent(new Label("This home page is displayed (with a notification if you type a wrong URL. Try this:")); PageResource pageResource = new PageResource(Ticket.class, "ABC"); vLayout.addComponent(new Link(pageResource.getURL(), pageResource)); String wrongUrl = "#NonExistingPage"; vLayout.addComponent(new Link(wrongUrl, new ExternalResource(wrongUrl))); mainLayout.addComponent( vLayout ); mainLayout.addComponent(gl); gl.setSizeFull(); gl.setSpacing(true); for (int i = 0; i < 9; i++) { Panel p = new Panel("Board " + i); gl.addComponent(p); p.setSizeFull(); } } }
Links
Compatibility
Was this helpful? Need more help?
Leave a comment or a question below. You can also join
the chat on Discord or
ask questions on StackOverflow.
Version
Added parameter injection.
[code] public class ProductPage extends VerticalLayout implements ParamChangeListener {
@Param(pos=0, required=true) Product p; // "34"
@Param(pos=1) String value1; // "AAAA"
@Param(pos=2) String value2; // "BBBB"
@Param String namedValue; // "namedValue=CCCC"
....
[/code]
and SEO enabled pages: @Page(crawlable=true)
- Released
- 2010-06-23
- Maturity
- BETA
- License
- Apache License 2.0
Compatibility
- Framework
- Vaadin 6.2+
- Vaadin 6.0+ in 7.0
- Browser
- N/A
Vaadin Add-on Directory
Find open-source widgets, add-ons, themes, and integrations for your Vaadin application.