2012年3月26日星期一

ADF_115:如何使用Dialog Framework?

运行环境:JDeveloper 11.1.2.2.0 + Oracle Database 10g Express Edition 10.2.0.1。
以前如果想要打开一个窗口,需要使用JavaScript;如果窗口中有多个页面,需要自己写代码管理。
使用ADF Dialog Framework,无需使用JavaScript,就可以很方便地打开一个窗口并管理窗口中的页面。
使用ADF Dialog Framework的方法非常简单:
(1)在导航规则中,以dialog:开头,导航到要在窗口中显示的页面。
(2)在命令组件上,action属性选择以dialog:开头的规则。
(3)在命令组件上,useWindow属性设置为true。

举例说明:一个用户注册的页面流如下:
(1)login.jsf
登录页面,登录成功,进入orders.jsf;登录失败,弹出一个窗口,显示error.jsf。
新用户可以点击New User?链接创建账户,弹出一个窗口,显示newAccount.jsf。
(2)error.jsf
登录失败页面,点击Back按钮,关闭弹出窗口,控制权返回login.jsf。
(3)orders.jsf
登录成功页面。
(4)newAccount.jsf
输入用户信息,点击Detail按钮,进入accountDetail.jsf,注意,此时仍在弹出的窗口中。
(5)accountDetail.jsf
输入用户账户信息,点击Done按钮提交,关闭弹出窗口, 控制权返回login.jsf,并把账户和口令传递给login.jsf,并显示出来 。
或点击Cancel按钮取消, 关闭弹出窗口, 控制权返回login.jsf。

重点步骤说明:
1. login.jsf

<af:form id="f1">
  <af:inputText label="User Name:" id="it1" value="#{backing_login.username}" partialTriggers="cl1" />
  <af:inputText label="Password:" id="it2" value="#{backing_login.password}" partialTriggers="cl1" />
  <af:commandButton text="Login" id="cb1" action="#{backing_login.handleLogin}" useWindow="true"/>
  <af:spacer width="10" height="10" id="s1"/>
  <af:commandLink text="New user?" id="cl1" action="dialog:new_account" useWindow="true" partialSubmit="true"
                  launchListener="#{backing_login.handleLaunch}"
                  returnListener="#{backing_login.handleReturn}" windowHeight="300" windowWidth="500"/>
</af:form>

说明:
(1)action=下一个导航目的地。必须以dialog:打头,这样ADF Faces才知道要把下一个页面以dialog形式打开。
(2)useWindow="true"。 表明下一个导航目的地,将使用dialog展现。
(3)windowHeight和windowWidth
(4)windowEmbedStyle
=inlineDocument,popup dialog与原始页面是同一个view id。
=window,popup dialog 单独使用一个view id。
(5)windowModalityType
=applicationModal,modal模式。
=modeless,非modal模式。
(6)launchListener=某个Backing Bean中的一个方法。
弹出窗口显示时调用的方法,可以用来传递参数给弹出窗口。
(7)returnListener=某个Backing Bean中的一个方法。
弹出窗口关闭时调用的方法,可以用来接收弹出窗口的返回参数。
(8)partialSubmit="true"。
防止popup dialogx显示时,原始页面被reloading。
(9)设置username 和password的patialTriggers指向commandLink
这样,当弹出窗口关闭时,会自动刷新这两个字段。

2. accountDetail.jsf

<af:form id="f1">
    <af:inputText label="Username:" id="it1"  value="#{pageFlowScope.firstName}"/>
    <af:inputText label="Password:" id="it2"  value="#{pageFlowScope.password}"/>
    <af:inputText label="Confirm Password:" id="it3"  value="#{pageFlowScope.confirmPassword}"/>
    <af:commandButton text="Cancel" id="cb1">
        <af:returnActionListener/>
    </af:commandButton>
    <af:commandButton text="Done" id="cb2" actionListener="#{backing_login.done}" />
</af:form>

说明:
(1)对于Cancel按钮,可以设置immediate="true",更重要的是要设置Return Action Listener,它会调用returnFromDialog方法,即关闭弹出窗口,并返回null。
(2)对于Done按钮,在Managed Bean的方法中调用returnFromDialog方法,该方法可以返回一个java.lang.Object或java.util.Map对象。即关闭弹出窗口,并返回参数值。

3. Managed Bean的完整代码

package view;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import oracle.adf.view.rich.context.AdfFacesContext;

import org.apache.myfaces.trinidad.event.LaunchEvent;
import org.apache.myfaces.trinidad.event.ReturnEvent;


public class LoginBackingBean {
    public LoginBackingBean() {
    }
    // Use by inputText value binding
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPassword() {
        return password;
    }

    public String handleLogin() {
        String retValue = "dialog:error";
        if (password != null && password.equals("oracle")) {
            retValue = "success";
        }
        return retValue;
    }

    public void handleLaunch(LaunchEvent launchEvent) {
        //Pass the current value of the field into the dialog
        Object usr = username;
        launchEvent.getDialogParameters().put("hello", "maping");      
    }

    public void handleReturn(ReturnEvent returnEvent) {
        if (returnEvent.getReturnValue() != null) {
            Customer cst = (Customer)returnEvent.getReturnValue();
            username = cst.getFirstName();
            password = cst.getPassword();
        }
    }

    public void done(ActionEvent e) {
        AdfFacesContext afContext = AdfFacesContext.getCurrentInstance();
        System.out.println("################## " + afContext.getPageFlowScope().get("hello"));
        String firstName = afContext.getPageFlowScope().get("firstName").toString();
        String lastName = afContext.getPageFlowScope().get("lastName").toString();
        String street = afContext.getPageFlowScope().get("street").toString();
        String zipCode = afContext.getPageFlowScope().get("zipCode").toString();
        String password = afContext.getPageFlowScope().get("password").toString();
        String confirmPassword = afContext.getPageFlowScope().get("confirmPassword").toString();
        if (!password.equals(confirmPassword)) {
            FacesMessage fm = new FacesMessage();
            fm.setSummary("Confirm Password");
            fm.setDetail("You've entered an incorrect password. Please verify that you'veentered a correct password!");
            FacesContext.getCurrentInstance().addMessage(null, fm);
        } else {
            //Get the return value
            Customer cst = new Customer();
            cst.setFirstName(firstName);
            cst.setLastName(lastName);
            cst.setStreet(street);
            cst.setZipCode(zipCode);    
            cst.setPassword(password);
            // And return it
            afContext.getCurrentInstance().returnFromDialog(cst, null);
            afContext.getPageFlowScope().clear();
        }
    }
}

说明:
(1)当窗口弹出时,命令组件上的launchListener将被调用,通过调用getDialogParameters把参数/参数值放到一个Map中,该Map可以把通过pageFlowScope访问到。
(2)当弹出窗口关闭时,命令组件上的returnListener将被调用,返回参数值可以通过returnEvent.getReturnValue()获得。

Project 下载:ADF_Dialog_Framework.7z

参考文献:

1.《Fusion Developer's Guide for Oracle ADF》之 Using the ADF Faces Dialog Framework
2. http://andrejusb.blogspot.com/2011/08/adf-dialog-framework-and-adf-task-flow.html
3. http://www.oracle.com/technetwork/developer-tools/jdev/index-095233.html
4. http://www.oracle.com/technetwork/cn/testcontent/index-101017-zhs.html
5. https://forums.oracle.com/forums/thread.jspa?threadID=550661

6. http://www.yaosansi.com/post/605.html
7. http://oracleseeker.com/2009/12/30/adf_dialog_inlinepopup_11g/

没有评论: