SPA (Simple-page-application) example

Description

To build a SPA application using Tapestry we can use the Zone's system. You have to keep in mind:

Demo

Page 1

Click on submit button to check navigation between pages internally

Source

package es.carlosmontero.webapp.t5devutil.pages.specialpages.spa;

import org.apache.tapestry5.Block;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.InjectComponent;
import org.apache.tapestry5.annotations.InjectPage;
import org.apache.tapestry5.corelib.components.Zone;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.PageRenderLinkSource;
import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.services.ajax.AjaxResponseRenderer;
import org.apache.tapestry5.services.ajax.JavaScriptCallback;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;

public class IndexPage {

   public enum PAGES {
      PAGE1(Block1Page.class), PAGE2(Block2Page.class), PAGE3(Block3Page.class);

      private final Class<?> clazz;

      private PAGES(final Class<?> clazz) {
         this.clazz = clazz;
      }

      public Class<?> getPageClass() {
         return clazz;
      }
   }

   @Environmental
   private JavaScriptSupport javaScriptSupport;

   @Inject
   private PageRenderLinkSource pageRenderLinkSource;

   @Inject
   private AjaxResponseRenderer ajaxResponseRenderer;

   @Inject
   private ComponentResources componentResources;

   @Inject
   private Request request;

   @InjectPage
   private Block1Page block1;

   @InjectPage
   private Block2Page block2;

   @InjectPage
   private Block3Page block3;

   @InjectComponent
   private Zone contentZone;

   private PAGES activePage;

   public void onActivate(final PAGES page) {
      activePage = page;
   }

   public Block getContentBlock() {

      if (activePage == null) {
         activePage = PAGES.PAGE1;
      }

      switch (activePage) {
      case PAGE1:
         return block1.getMainBlock();

      case PAGE2:
         return block2.getMainBlock();

      case PAGE3:
         return block3.getMainBlock();
      }

      return null;
   }

   public Object onBack(final PAGES page) {

      if (request.isXHR()) {
         activePage = page;
         ajaxResponseRenderer.addRender(contentZone);
         return null;
      }
      else {
         return page.getPageClass();
      }

   }

   public void onChangePage(final PAGES page) {
      activePage = page;
      ajaxResponseRenderer.addRender(contentZone);
      ajaxResponseRenderer.addCallback(new JavaScriptCallback() {
         @Override
         public void run(final JavaScriptSupport javascriptSupport) {

            final String restoreUrl = componentResources.createEventLink("back", page).toAbsoluteURI();
            final String newUrl = pageRenderLinkSource.createPageRenderLink(page.getPageClass()).toAbsoluteURI();

            javascriptSupport.require("spa").invoke("selectpage")
                    .with(
                            restoreUrl,
                            page + " title",
                            newUrl
                    );
         }
      });
   }

   public void setupRender() {
      javaScriptSupport.require("spa").invoke("init");
   }

}