5 Replies Latest reply: Nov 6, 2012 11:14 AM by lewarrior22 RSS

Is there a way to navigate beetwen pages with Errai?

n3k0 Newbie

Or... do we have to wait for a GWT official way to do that. Or just we have to use another alternative like gwtpages or gwt-multipage ?

  • 1. Re: Is there a way to navigate beetwen pages with Errai?
    Jonathan Fuerth Master

    Good question.

     

    At the moment, we don't have anything in Errai for handling page-to-page navigation. If you do try out gwtpages or gwt-multipage, please come back and share your experiences!

     

    -Jonathan

  • 2. Re: Is there a way to navigate beetwen pages with Errai?
    Lincoln Baxter III Master

    GWT Multipage looks like a dead project, but you can also use the MVP (Model View Presenter) pattern from GWT itself:

     

    https://developers.google.com/web-toolkit/doc/latest/DevGuideMvpActivitiesAndPlaces

     

    Some example code from SocialPM:

     

    https://github.com/ocpsoft/socialpm/tree/master/gwt/src/main/java/com/ocpsoft/socialpm/gwt/client/local/view/login

    https://github.com/ocpsoft/socialpm/blob/master/gwt/src/main/java/com/ocpsoft/socialpm/gwt/client/local/AppPlaceHistoryMapper.java

     

    This also utilises OCPsoft Rewrite for managing the URL history state and bookmarkability of URLs:

     

    http://ocpsoft.org/rewrite/

    https://github.com/ocpsoft/rewrite/tree/master/integration-gwt

    https://github.com/ocpsoft/socialpm/blob/master/gwt/src/main/java/com/ocpsoft/socialpm/gwt/server/history/HistoryRewriteConfiguration.java

     

    You still have to do link generation yourself, but at least the URLs and bookmarking work at this point. You just need to add a new Activity and Place for each URL you want to expose... typically you also add a new View.

     

    Hope this helps,

    Lincoln

  • 3. Re: Is there a way to navigate beetwen pages with Errai?
    n3k0 Newbie

    Challenge accepted ;-)

     

     

     

    Ok, ok, sorry about my late reply.

     

    This is my experience with the gwtpages framework, and i'll detail it with a (simplest) example.

     

    First we have to include the gwtpages library to the project classpath, and include its reference in the (The name you like ).gwt.xml

     

    <module rename-to="yourApp">
        <inherits name="com.google.gwt.user.User" />
        <inherits name="com.google.gwt.user.theme.standard.Standard"/>
        <inherits name="com.google.gwt.i18n.I18N" />
        <inherits name="org.jboss.errai.bus.ErraiBus" />
        <inherits name="org.jboss.errai.ioc.Container" />
        <inherits name="org.jboss.errai.enterprise.CDI" />
        <inherits name="com.google.gwt.gwtpages.GWT_Pages" />
        <source path="client" />
        <source path="shared" />
    </module>
    

     

    After that, we have to put some .java code to configure gwtpages.

     

    1.- BasePage.java

    2.- PageConstants.java

    3.- PageLoader.java

    4.- MyEntryPoint.java

     

     

    1.- BasePage.java

        This file (like the name says) is the "Base" for the Views that we want to control through gwtpages framework.

        This file extends FlowPanel ( it can be SimplePanel too ) and implements Page.

        We can to extend this class or implement the Page interface and extends some Panel.

     

    public class BasePage extends FlowPanel implements Page{
    
        @Override
        public void init(Pages pages) throws Exception {}
    
        @Override
        public void destroy(Pages pages) {}
    
        @Override
        public void onEnterPage(PageParameters parameters,
                PageRequestSession session, AsyncPageCallback callback)
                throws Exception {}
    
        @Override
        public void onExitPage() {}
    
        @Override
        public Widget asWidget() {
            return this;
        }
    }
    

     

     

    2.- PageConstants.java

        This interface is "nice to have", and we will put all the Strings that represents our "pages" in the app.

        We can put all the Strings in a, i don't know, an enum or something else ;-)

     

    public interface PageConstants {
        public static final String DESKTOP_PAGE = "desktopPage";
    }
    

     

    3.- PageLoader.java

        This class must extends some "Loader" ( in this example is the AsyncLoader ), in this class, we put the "Pages"

        that we want to control by gwtpages framework.

     

    public class PageLoader extends AsyncPageLoader {
    
        @Override
        public void registerPages() {
            registerPage(PAGE_DEFAULT, Login.class); // don't create a constant PAGE_DEFAULT, just create constants for the other pages, PAGE_DEFAULT is already built =)
            registerPage(PageConstants.DESKTOP_PAGE, DesktopPage.class);
        }    
    }
    

     

    4.-MyEntryPoint.java

        This class will be the original EntryPoint in the application, it creates the "Presenter" to our app, paste it to the root

        component, inits the PageLoader and shows the first page.

     

    @EntryPoint
    public class MyEntryPoint {
    
        @PostConstruct
        public void onModuleLoad() {            
            // create the application presenter and add it to the root (this is the simplest of them)
            SimplePanelApplicationPresenter applicationPresenter = new SimplePanelApplicationPresenter();
            RootPanel.get().add(applicationPresenter);
    
            // initialize the pages settings
            Pages.init( (PageLoader) GWT.create(PageLoader.class), applicationPresenter, new HandlerManager(null), true) // we want to listen to history tokens
                 .addDefaultEventHandlers() // add default behavior if desired
                 .showStartPage(true); // show the first page while checking the history token
        }
    }
    

     

    It's all about configure, separately, i have my two "Pages":

     

    Login.java

     

    public class Login extends BasePage implements ClickHandler {
        private TextBox textBox;
        private PasswordTextBox passwordTextBox;
        private Button button;
        private VerticalPanel verticalPanel;
    
        public Login() {
            this.onModuleLoad();
        }
    
        public void onModuleLoad() {
    
            final DecoratorPanel decoratorPanel = new DecoratorPanel();
            final AbsolutePanel absolutePanel = new AbsolutePanel();
            absolutePanel.setSize("383px", "237px");
    
            textBox = new TextBox();
            absolutePanel.add(textBox, 196, 46);
    
            passwordTextBox = new PasswordTextBox();
            absolutePanel.add(passwordTextBox, 196, 97);
    
            button = new Button("Log in");
            button.addClickHandler(this);
    
            absolutePanel.add(button, 186, 158);
    
            Label lblUsername = new Label("User");
            absolutePanel.add(lblUsername, 75, 47);
    
            Label lblPassword = new Label("Password");
            absolutePanel.add(lblPassword, 75, 98);
    
            Label lblRegisteredUser = new Label("Registered users");
            absolutePanel.add(lblRegisteredUser, 122, 10);
    
            decoratorPanel.add( absolutePanel );
    
            verticalPanel = new VerticalPanel();
            verticalPanel.add( decoratorPanel );
            verticalPanel.setSize("100%", "100%");
            verticalPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
            verticalPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
            verticalPanel.setCellVerticalAlignment(decoratorPanel, HasVerticalAlignment.ALIGN_MIDDLE);
            verticalPanel.setCellHorizontalAlignment(decoratorPanel, HasHorizontalAlignment.ALIGN_CENTER);
    
            this.add(verticalPanel);
        }
    
        @Override
        public void onClick(ClickEvent event) {
            if(event.getSource().equals(button)){
                String u = textBox.getValue();
                String p = passwordTextBox.getValue();
    
                if(u == null || u.isEmpty() || p == null || p.isEmpty() ){
                    Window.alert("Type a valid username/password");
                }
                else{
                    this.executeAuthentication(u, p);
                }
            }
        }
    
        private void executeAuthentication( final String usr , final String password ){
            MessageBuilder.createCall(new RemoteCallback<Long>() {      
                @Override
                public void callback(Long response) {
                    if( response != null && response > 0 ){
                        Pages.get().goTo( PageConstants.DESKTOP_PAGE , usr, password ).execute(); //send usr and pass just to show how to send parameters
                    }
                }                                                           
            }, UserService.class).authenticate( usr , password );
        }
    }
    

     

    And DesktopPage.java

     

    public class DesktopPage extends BasePage implements ClickHandler {
    
        private Label paramLabel;
    
        public MonitorDesktop() {
                add(new Label("The parameters are: "));
                add(this.paramLabel  = new Label());
        }
    
        @Override
        public void onEnterPage(PageParameters parameters,PageRequestSession session, AsyncPageCallback callback) {
                StringBuilder sb = new StringBuilder();
                for (int i=0; i<parameters.listSize(); i++) {
                        if (sb.length() > 0) sb.append(", ");
                        sb.append(parameters.asString(i));
                }
                paramLabel.setText(sb.toString());
        }
    }
    

     

    As i said, this is a very very simple example of the basic features of the framework, but i don't need anymore, if you want to know more about it, you can go to it's homepage http://code.google.com/p/gwtpages/  to get more info, read the wiki and check the examples.

     

    Note: download the source and compile your own version of gwtpages to work 100% with your version of gwt ( I did with gwt 2.4).

     

    Felices trazos.

     

    I mean, happy coding!

  • 4. Re: Is there a way to navigate beetwen pages with Errai?
    Jonathan Fuerth Master

    Wow, thanks!

     

    That's an excellent walkthrough of the gwtpages framework. I'm sure this will be useful to many others.

     

    Glad to see you've got your page navigation up and running!

     

    -Jonathan

  • 5. Re: Is there a way to navigate beetwen pages with Errai?
    lewarrior22 Newbie

    Hi, Sorry if It is the wrong place to post.

     

    I'm looking for a way to do achieve this with @Template views. It will be amaizingly good from  errai.

     

    @EntryPoint

    @Templated("#homeview")

    public class HomeView extends Composite{

    @Inject

    @DataField

              private Hyperlink homeLink ;

    @Inject

    @DataField

              private Hyperlink aboutLink ;

     

    @Inject

    @DataField

              private Hyperlink contactLink ;

    @Inject

    @DataField

    private Button createAccountBtn ;

    @Inject

    @DataField

              private Button loginBtn ;

     

    @DataField

              private HTMLPanel main = new HTMLPanel("");

     

    @Inject

              private Instance<AboutUsView> aboutUsViewInstance ;

    @Inject

              private Instance<CreateAccountView> createAccountViewInstance ;

    @Inject

              private Instance<HomeViewMainContent> mainContentViewInstance ;

     

     

    @PostConstruct

              public void init(){

                        Window.alert("Initializing ...");

      this.main.add(mainContentViewInstance.get());

                        RestClient.setJacksonMarshallingActive(false);

                    RootPanel.get("kitchensink").add(this);

              }

     

    @EventHandler("aboutLink")

              public void onAboutLinkClicked(ClickEvent click){

                        AboutUsView aboutUsView = aboutUsViewInstance.get();

                        Window.alert("Initializing ...");

                        RootPanel rootPanel = RootPanel.get("kitchensink");

                        rootPanel.clear();

                        rootPanel.add(aboutUsView);

              }

     

    @EventHandler("createAccountBtn")

              public void onCreateAccountClicked(ClickEvent click){

                        Window.alert("Initializing ...");

                        main.clear();

                        CreateAccountView createAccountView = createAccountViewInstance.get();

                        main.add(createAccountView);

                        createAccountView.setMain(main);

              }

     

              public HTMLPanel getMain() {

      return main;

              }

     

              public void setMain(HTMLPanel main) {

                        this.main = main;

              }

    }

     

    //@Page

     

    //@Dependent

     

    @Singleton

    @Templated("#createAccountView")

    public class CreateAccountView extends Composite {

     

     

              @Inject

              @DataField

              private TextBox id ;

     

     

     

     

              @Inject

              @Bound

              @DataField

              private TextBox name ;

     

     

              @Inject

              @Bound

              @DataField

              private TextBox login ;

     

     

     

              //automatically bind account.password to the widget password

              @Bound

              @Inject

              @DataField

              private TextBox password;

     

     

     

              @Inject

              @DataField("webSiteUi")

              private TextBox webSite ;

     

     

     

              @Inject

              @DataField

              private TextBox email ;

     

     

              @Inject

              @DataField

              private TextBox btnSave  ;

     

              @Inject

              @AutoBound

              private DataBinder<Account> accountDataBinder ;

     

              @Inject

              private Event<Account> accountEvent ;

              private HTMLPanel main ;

     

              @Inject

              private Caller<AccountService> accountServiceCaller ;

     

     

              @Inject

              private Caller<AccountRESTService> accountRestServiceCaller ;

     

              @Inject

              private Instance<HomeView> homeView ;

              @PostConstruct

              public void init(){

                        accountDataBinder.bind(id, "id");

                        accountDataBinder.bind(webSite, "website");

              }

              @EventHandler("btnSave")

              public void onBtnSaveClicked(ClickEvent click){

                        //use the model to retrieve data from the form

                        Account account = accountDataBinder.getModel();

                        RemoteCallback<Account> remoteCallback = new RemoteCallback<Account>() {

                                  @Override

                                  public void callback(Account response) {

                                            Window.alert("Account Created from server !"+response);

                                  }

                                  };

                        ErrorCallback errorCallback = new ErrorCallback() {

     

                                  @Override

                                  public boolean error(Message message, Throwable throwable) {

                                            if(throwable instanceof TransportIOException){

     

     

                                                      Window.alert("Could Reach the server : ["+message+"]  \n and ["+throwable+"]" );

                                            }else {

                                                      Window.alert("Marschalling errors ["+message+"]  \n and ["+throwable+"]" );

                                                      // kitchensink main_com

                                                      RootPanel.get("kitchensink").add(new CreateAccountView());

                                            }

                                            return true;

                                  }

                        };

    //                    accountServiceCaller.call(remoteCallback,errorCallback).create(account);

    //                    accountRestServiceCaller.call(remoteCallback, errorCallback).create(account);

                        RestClient.setJacksonMarshallingActive(true);

                        Window.alert("Save acount "+account+"  \n path"+RestClient.getApplicationRoot()+"\n jackson  : "+RestClient.isJacksonMarshallingActive());

                        ResponseCallback responseCallback = new ResponseCallback() {

     

                                  @Override

                                  public void callback(Response response) {

                                            Window.alert("Account Created from server !"+response.getText());

                                  }

                        };

                        RestClient.create(AccountRESTService.class, responseCallback, errorCallback,new Integer[0]).create(account);

                        // kitchensink main_com

                        RootPanel.get("kitchensink").add(this);

              }

     

              public HTMLPanel getMain() {

                        return main;

              }

              public void setMain(HTMLPanel main) {

                        this.main = main;

              }

    }

     

    but after every click on the saveBtn, It bring me back to the home view.  Do some one has an idea

    thanks.