JSF2.0 Ajax Navigation Pattern - PullRequest
       0

JSF2.0 Ajax Navigation Pattern

2 голосов
/ 14 октября 2011

Буду признателен за некоторые рекомендации относительно шаблонов для веб-приложений, использующих JSF 2.0, PrimeFaces и Ajax. Наша текущая система использует JSP со стандартными отправками, и у нас есть 1 JSP для каждой функциональной страницы в нашем приложении. Каждый JSP вызывает класс действия для вызовов логики, навигации и EJB. Переход на JSF с использованием той же настройки будет относительно простым, т. Е. 1 страница HTML и связанный с ним компонент поддержки и навигация / логика выполняются с помощью метода do. Однако мы хотим отправить через Ajax, и это вызывает загадки в моей голове. Если я загружаю abc1.xhtml и отправляю с ajax, то я остаюсь на abc1.xhtml, хотя мне может понадобиться перейти на abc2.xhtml. Я подумал о том, чтобы иметь связанные формы на 1 странице HTML и использовать отображаемое свойство, чтобы решить, что отображать. Это работает, но мне неудобно иметь много форм на 1 странице. В идеале я хочу сохранить каждую страницу отдельной, но не знаю, как это возможно с Ajax. Любые идеи будут высоко оценены.

Редактировать - это было оригинальное решение, но теперь оно было уточнено в моем ответе ниже . Это работает, но, похоже, есть проблемы с Params. Когда я нажимаю на ссылку AAA или BBB, мне нужно передать параметр, чтобы бин ViewController знал, что было нажато и где установить страницу назначения. Однако, если я нажму кнопку «Отправить» в AAA.xhtml, содержимое не изменится, если я не добавлю <f:param name="tranID" value="AAA"/> к командной кнопке. Я думал, что обработал нулевой Param в конструкторе ViewController, но, очевидно, я упускаю что-то важное. Мои единственные мысли были связаны с URL. Когда я нажимаю на ссылку меню, он добавляет параметр в URL ?tranID=AAA. Если я не добавлю параметр в последующую отправку, это эффективно изменит URL и вызовет какое-то несоответствие?

viewController.xhtml

<h:body>
    <h:panelGroup layout="block" id="transactionControl">

                    <h4>
                        <h:outputLink id="mfa" value="#{facesContext.externalContext.requestContextPath}/xhtml/viewController.xhtml" styleClass="menuLink">
                            <h:outputText value="AAA"></h:outputText>
                            <f:param name="tranID" value="AAA"/>
                        </h:outputLink>
                    </h4>

                    <h4>
                        <h:outputLink id="inq" value="#{facesContext.externalContext.requestContextPath}/xhtml/viewController.xhtml" styleClass="menuLink">
                            <h:outputText value="BBB"></h:outputText>
                            <f:param name="tranID" value="BBB"/>
                        </h:outputLink>
                    </h4>



    </h:panelGroup>

    <h:panelGroup layout="block" id="content" style="border-style: solid;">

        <ui:include src="#{viewController.destinationPage}.xhtml"></ui:include>

    </h:panelGroup>

</h:body>

AAA.xhtml

<h:body>
    <h:form prependId="false">
        <h:outputText value="Click the button to go to AAB"></h:outputText>

        <p>
            <p:commandButton id="submitButton" value="Go" ajax="true" actionListener="#{viewController.doAAAtoAAB}"
                             process="@form"
                             update="content">
                <f:param name="tranID" value="AAA"/>
            </p:commandButton>
        </p>

    </h:form>

</h:body>

AAB.xhtml

<h:body>
    <h:panelGroup layout="block" id="subContent">
        <h:outputText value="This is the AAB content"></h:outputText>
    </h:panelGroup>
</h:body>

BBB.xhtml и BBC.xhtml, как указано выше

Боб ViewController

package com.mcpplc.supportclient.webapp.managedBeans;


import javax.faces.context.FacesContext;    
import java.io.Serializable;

@ManagedBean
@ViewScoped
public class ViewController implements Serializable
{
    String destinationPage = "splash";
    FacesContext context;
    String callingTranID;

    public ViewController ()
    {
        context = FacesContext.getCurrentInstance();
        callingTranID = context.getExternalContext().getRequestParameterMap().get("tranID");

        if (callingTranID != null )
        {
            destinationPage = callingTranID;
        }
    }


    public void doAAAtoAAB()
    {
         destinationPage = "AAB";
    }

    public void doBBBtoBBC()
    {
         destinationPage = "BBC";
    }

    public String getDestinationPage()
    {
        return destinationPage;
    }

    public void setDestinationPage( String destinationPage )
    {
        this.destinationPage = destinationPage;
    }
}

Ответы [ 2 ]

0 голосов
/ 21 октября 2011

Решил ответить на свой вопрос, так как у меня теперь есть полнофункциональное приложение с прототипом ajax only. Это соответствует моим первоначальным требованиям, чтобы каждое представление сохранялось как одна страница .xhtml, а каждое представление имеет свой собственный компонент поддержки. Вместо дальнейшего загрязнения мой вопрос здесь упрощенный код. (Спасибо BalusC за его предыдущий ответ, который действительно помог, хотя теперь он исчез).

viewController.xhtml

<h:body>
    <h:panelGroup layout="block" id="transactionControl">

                    <h:form>
                <h4>

                    <p:commandLink id="mfa" ajax="true" process="@form" update="content transactionBannerContent" styleClass="menuLink" oncomplete="showTransaction01Screens();">
                        <h:outputText value="MFA"></h:outputText>
                        <f:setPropertyActionListener target="#{viewController.destinationPage}" value="MFA01"/>
                    </p:commandLink>

                </h4>

                <h4>
                    <p:commandLink id="inq" ajax="true" process="@form" update="content transactionBannerContent" styleClass="menuLink" oncomplete="showTransaction01Screens();">
                        <h:outputText value="INQ"></h:outputText>
                        <f:setPropertyActionListener target="#{viewController.destinationPage}" value="INQ01"/>                            
                    </p:commandLink>


                </h4>

            </h:form>



    </h:panelGroup>

    <h:panelGroup layout="block" id="content" style="border-style: solid;">

        <ui:include src="#{viewController.destinationPage}.xhtml"></ui:include>

    </h:panelGroup>

</h:body>

mfa01.xhtml

<h:panelGroup layout="block" id="mfa01">

            <h:form id="mfa01Form">

                <p>
                    <span>
                        <h:outputLabel value="UCN" for="ucn"/>
                        <h:inputText id="ucn" value="#{mfa01BackingBean.mfa01FormVO.ucn}" size="20"/>
                    </span>
                </p>


                <p class="submitButton">
                    <p:commandButton id="submitButton" value="Go" ajax="true" actionListener="#{mfa01BackingBean.doMFA01}" process="@form"
                                     update="content transactionBannerContent" oncomplete="ajaxFinished('MFA01')">
                    </p:commandButton>
                </p>

            </h:form>

        </h:panelGroup>

mfa02.xhtml

<h:panelGroup layout="block" id="mfa02">


            <h:form id="mfa02Form" prependId="true">

                <p>
                    <span style="width:25%">
                        <h:outputLabel value="Vessel Name"/>
                        <h:outputText id="vesselName"
                                     value="#{mfa02BackingBean.mfa02FormVO.vesselName}"/>
                    </span>


                    <span style="width:75%">
                        <h:outputLabel value="ETA"/>
                        <h:outputText id="eta"
                                     value="#{mfa02BackingBean.mfa02FormVO.eta}"/>
                    </span>

                </p>




                <p>
                    <span>
                        <h:outputLabel value="Unit ID" for="unitID"/>
                        <h:inputText id="unitID"
                                     value="#{mfa02BackingBean.mfa02FormVO.unitID}"
                                     size="20"
                                     required="true" validator="#{mfa02BackingBean.validateData}"/>
                    </span>
                </p>


                <p class="submitButton">
                    <p:commandButton id="submitButton" value="Go" ajax="true" action="#{mfa02BackingBean.doMFA02}"
                                     process="@form" update="content transactionBannerContent" oncomplete="ajaxFinished('MFA02')">
                        <f:param name="randomString" value="AAA"/>
                                     </p:commandButton>
                </p>


            </h:form>
        </h:panelGroup>

ViewController.java

package com.mcpplc.supportclient.webapp.managedBeans;


import javax.faces.bean.*;
import java.io.Serializable;

@ManagedBean (name = "viewController")
@SessionScoped
public class ViewController implements Serializable
{
    String destinationPage = "splash";
    String transactionID;


    public String getDestinationPage()
    {
        return destinationPage;
    }

    public void setDestinationPage( String destinationPage )
    {
        this.destinationPage = destinationPage;
        transactionID = destinationPage.toUpperCase();
    }

    public String getTransactionID()
    {
        return transactionID;
    }

    public void setTransactionID( String transactionID )
    {
        this.transactionID = transactionID;
    }
}

mfa01BackingBean.java

package com.mcpplc.supportclient.webapp.managedBeans;

import com.mcpplc.supportclient.webapp.Utils.JSFUtils;
import com.mcpplc.supportclient.webapp.valueObjects.*;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;

@ManagedBean
@RequestScoped
public class Mfa01BackingBean
{
    @ManagedProperty(value = "#{viewController}")
    private ViewController viewController;

    private ImportConsignmentVO importConsignmentVO;
    private VoyageVO voyageVO;

    private Mfa01FormVO mfa01FormVO;

    private Mfa02FormVO mfa02FormVO;

    @PostConstruct
    public void init()
    {
        mfa01FormVO = new Mfa01FormVO();
    }

    public void doMFA01()
    {
        //pretend to get VOs
        importConsignmentVO = new ImportConsignmentVO();
        voyageVO = new VoyageVO();

        //set some VO stuff
        if ( mfa01FormVO.getUcn().equalsIgnoreCase( "123" ) )
        {
            importConsignmentVO.setUnitID("AJF1");
            voyageVO.setVesselName("Ever Glade");
        }
        else {
            importConsignmentVO.setUnitID("ZZZ1");
            voyageVO.setVesselName("Ever Champion");
        }
        importConsignmentVO.setType("41G1");
        importConsignmentVO.setWeight("25000");
        voyageVO.setEta("01/01/2011");

        constructMFA02Form();

        viewController.setDestinationPage("mfa02");

    }

    private void constructMFA02Form()
    {
        mfa02FormVO = new Mfa02FormVO();
        mfa02FormVO.setUnitID(importConsignmentVO.getUnitID());
        mfa02FormVO.setType(importConsignmentVO.getType());
        mfa02FormVO.setWeight(importConsignmentVO.getWeight());
        mfa02FormVO.setMfaRef("12345");
        mfa02FormVO.setVesselName(voyageVO.getVesselName());
        mfa02FormVO.setEta(voyageVO.getEta());

        JSFUtils.addObjectToRequest(Mfa02FormVO.class.getName(), mfa02FormVO);
    }

  .....getters&setters

}

mfa02BackingBean.java

package com.mcpplc.supportclient.webapp.managedBeans;

import com.mcpplc.supportclient.webapp.Utils.JSFUtils;
import com.mcpplc.supportclient.webapp.valueObjects.*;

import java.io.Serializable;
import java.util.*;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;

@ManagedBean
@ViewScoped
public class Mfa02BackingBean implements Serializable
{
    @ManagedProperty(value = "#{viewController}")
    private ViewController viewController;


    private Mfa02FormVO mfa02FormVO;    

    @PostConstruct
    public void init()
    {
       mfa02FormVO = (Mfa02FormVO) JSFUtils.getObjectFromRequest(Mfa02FormVO.class.getName());

    }

    public String doMFA02()
    {
        viewController.setDestinationPage("mfa01");
        return "viewController";
    }


     public void validateData ( FacesContext facesContext, UIComponent uiComponentToValidate, Object value)
    {
        String message = "";
        String requestData = (String) value;
        if ( !requestData.contains( "0" )  )
            {
                ((UIInput )uiComponentToValidate).setValid( false );
                message = "Incorrect format for Unit ID";
                facesContext.addMessage( uiComponentToValidate.getClientId(facesContext), new FacesMessage(message) );
                //JSFUtils.addObjectToRequest(Mfa02FormVO.class.getName(), mfa02FormVO);

            }



    }

.....getters&setters
}

Mfa01FormVO и Mfa02FormVO - просто объекты значений с геттерами и сеттерами

Основной проблемой, с которой я столкнулся, было сохранение данных объекта между запросами. Когда я перехожу из mfa01 в mfa02, я делаю поиск, заполняю некоторые vos и затем передаю форму vo во Flash. Затем экран Mfa02 создается со значениями vo. Большая проблема у меня была, когда произошла ошибка проверки на mfa02. Первоначально у меня был установлен bean-компонент requestScoped, однако я потерял объект vo после неудачной проверки. Это было несмотря на то, что я добавил объект обратно во вспышку, как только я получил его от Flash. Странно было то, что не было никакой гарантии, что я потеряю объект. Если бы я щелкнул снова, то я бы сразу потерял объект, но иногда он оставался бы еще на один щелчок, а затем я бы его потерял.

Затем я изменил mfa02backingbean на ViewScoped. Однако, поскольку это полностью ajax, mfa02backingbean не было повторно инициализировано при последующих запросах. Это означало, что все значения, которые я установил в первом запросе, будут отображаться всегда. В конце концов я решил эту проблему, используя ViewScoped и изменив Командную кнопку, чтобы использовать Action, а не ActionListener, и в этом методе я возвращаю строку «viewController». Я предполагаю, что жизненный цикл думает, что я возвращаюсь к новому представлению, поэтому он очищает все, что осталось в окне обзора.

Надеюсь, этот код поможет всем, кто ищет подобное решение.

0 голосов
/ 14 октября 2011

Я рекомендую вам не использовать ajax, если он вам не нужен.Если после запроса вам нужно вызвать другую страницу, какой смысл использовать ajax?

Попробуйте продумать рабочий процесс приложения и применить ajax там, где это необходимо.Вы думаете, что ajax может сбить вас с толку, потому что вы, вероятно, не должны использовать его

Cheers

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...