Show lookup details in popup (dialog) window using ADF Faces & JHeadstart 10.1.3

This article describes how to implement simple popup (dialog) windows with (lookup) details for specific fields in our web application. The application we discuss is based on ADF Faces and has been generated using JHeadstart 10.1.3 (beta – I have used Build 78). Most of the concepts from this article can be applied to ADF Faces applications not based on ADF Business Components and not generated using JHeadstart. The contents of this article is heavily inspired by the section on Deep Linking in the JHeadstart 10.1.3 Developer’s Guide – with the notable addition of using dialog windows as target for deep-link navigation.

The example we will develop in this article is a simple EMP-DEPT application. On the Form page where we see the Employee details, the name of the Department is actually a hyperlink that can be clicked on by the user. When clicked, a dialog window opens and displays the Department details.

Show lookup details in popup (dialog) window using ADF Faces & JHeadstart 10.1.3 deepCopyDialogRefined

....

Getting started with our HRM Application

The first step is normal JHeadstart procedure. Our starting point is the SCOTT schema (EMP and DEPT tables) and a JDeveloper 10.1.3 with JHeadstart 10.1.3 (build 78) installation.

Create the Model Project 

  1. Start JDeveloper
  2. Create a new Application; choose the Web Application [JSF, ADF BC] Application Template. Call the Application for example HRM. JDeveloper creates two projects: Model and ViewController.
  3. On the Model project, select from the New Gallery the option Business Tier, ADF Business Components, Business Components for Tables
  4. Select or Create a Connection to the SCOTT schema
  5. Select the tables EMP and DEPT to create Entity and Updateable ViewObjects for; accept the default package and application module names
  6. Define primary keys for the EMP and DEPT EntityObjects: Select the Emp EntityObject; select the EMPNO attribute, check the Primary Key Checkbox, select the RowID attribute and uncheck the Primary Key checkbox. Select the DEPT EntityObject, select the EMPNO attribute, check the Primary Key Checkbox, select the RowID attribute and uncheck the Primary Key checkbox.
  7. Remove the RowID attribute from both ViewObjects
  8. Select the EmpView ViewObject. Add Dept to the Model. Inspect the Join Condition (under the SQL Statement node); it should read: Emp.DEPTNO = Dept.DEPTNO. Add the Dname attribute. to the EmpView ViewObject.

This concludes the Model project. If you feel like testing it, you could run the Test option from the Right Mouse Button Menu on the AppModule Application Module.

Create and Generate the ViewController Project

Now we will generate a straightforward EMP and DEPT application

  1. From the RMB menu on the ViewController project, select the option Enable JHeadstart on this Project. Run and Finish the wizard.
  2. Again, from the RMB menu on the ViewController project, select the option New JHeadstart Application Definition. A wizard is run. Accept all defaults and Finish. A Default JHeadstart Application Definition file is created. Save All.
  3. You will find the new ApplicationDefinition file can be found under the node Resources in the ViewController project. Select the option Run JHeadstart Application Generator from the RMB menu on this file. The default application is now generated. Press Save All.
  4. Run the file EmpTable.jspx under ViewController\WebContent\WEB-INF\page to inspect the application.
    Show lookup details in popup (dialog) window using ADF Faces & JHeadstart 10.1.3 deepCopyDialogPlainEmp

Add the Deep Linking capability

Our objective is to be able to open a popup window from the Emp form-page with additional details about the Department in which the current Employee is working. To that end, we want to replace the Dname textinput with a hyperlink that shows the name of the department and – when clicked – brings up the dialog window.

Our first step is to use the Deep-Link functionality in JHeadstart. This will allow us to navigate to the Department Form page, but in same window instead of in a dialog popup window – that comes next.

  1. Deep-Link enable the target group (it took some time for me to realize that I had to enable the Dept group or the Deep-Link’s target group): go to the Dept group in the Application Definition Editor. Toggle from Novice Mode to Expert Mode. This introduces the Deep-Linking properties in the property palette.
    Show lookup details in popup (dialog) window using ADF Faces & JHeadstart 10.1.3 deepCopyDialogProps
  2. Set the Type of Deep Linking to: Query By Key Value. Set the Deep Linking Key Expression to #{param.deptno}
  3. Re-generate the application with the JHeadstart Application Generator.This will generate several deep-link related code fragments: the faces-config.xml file contains a global navigation case for the outcome DeepLinkDept always to navigate to Dept.jspx. The (ADF Binding) Page Definition for Dept.jspx (ViewController\src\view\pagedefs\DeptpageDef.xml) contains an executable with RefreshCondition="#{jsfNavigationOutcome==’DeepLinkDept’}" bound to the method queryByKeyValueDept which in turn invokes the method queryByKeyValue on the AppModule ApplicationModule – a method implemented in the JHeadstart JhsApplicationModuleImpl superclass. The #{param.deptno} is one of two input parameters to this method.
  4. Now we have to create the CommandLink in the Emp.jspx page to allow the user to click on the Department name. Open the Emp.jspx page. Locate the EmpDname InputText. Replace the InputText with the following PanelGroup:
    <af:panelGroup>
    <af:outputLabel value="Department"/>
    <af:objectSpacer width="20"/>
    <af:commandLink action="DeepLinkDept" id="EmpDname"
    text="#{bindings.EmpDname.inputValue}"
    <f:param name="deptno"
    value="#{bindings.EmpDeptno.inputValue}"/>
    </af:commandLink>
    </af:panelGroup>

  5. This creates a HyperLink that shows the name of the Department, with a preceding label (prompt) of Department. When the CommandLink is invoked (clicked upon), the global Navigation Case for outcome DeepLinkDept is executed which takes us to the Dept.jspx page. The Executable for the DeepLinkDept outcome is executed as specified in the PageDefinition and the QueryByKeyValue method on the Application Module is executed for the  department specified in #{param.deptno}, the value that was posted when the CommandLink was invoked.
    Show lookup details in popup (dialog) window using ADF Faces & JHeadstart 10.1.3 deepCopyDialogEmp

    Show lookup details in popup (dialog) window using ADF Faces & JHeadstart 10.1.3 deepCopyDialogDept

Navigating to a Dialog Window

As stated before, we want the navigation to takes to a dialog, popup window that shows the Department details for the current Employee, then can be closed again. We will make use of the "dialog"  mechanism in ADF Faces. We need to apply a few further changes – that we could make generatable using the JHeadstart templating mechanism, but for the moment will not.

  1. In the file faces-config.xml change the name of the from-outcome of the global deeplink navigation case from DeepLinkDept to dialog:DeepLinkDept. It is a requirement in ADF Faces that the From Outcome that takes us to a dialog window starts with dialog:
  2. In the file Emp.jspx, change the definition of the CommandLink element; it must navigate to the newly defined from outcome. And let’s also do it through a partial page submit, to reduce the screenactivity (partialSubm
    it="true"). Finally, to ensure a
    new window is opened, we need to specify useWindow="true":

    <af:commandLink useWindow="true" partialSubmit="true" 
    action="dialog:DeepLinkDept" id="EmpDname"
    text="#{bindings.EmpDname.inputValue}">
    <f:param name="deptno"
    value="#{bindings.EmpDeptno.inputValue}" />
    </af:commandLink>

  3. In the PageDefinition for the Dept.jspx file, we need to change the Executable queryByKeyValueDeptInvoke to the correct navigation outcome :
        <invokeAction id="queryByKeyValueDeptInvoke" Binds="queryByKeyValueDept"
    Refresh="prepareModel"
    RefreshCondition="#{jsfNavigationOutcome=='dialog:DeepLinkDept'}"/>

  4. Run the file Emp.jspx.
    Show lookup details in popup (dialog) window using ADF Faces & JHeadstart 10.1.3 deepCopyDialogUnrefined

Refine the Dialog Window

At this point, we have it all working. However, we are not quite done. The Dialog Window contains the normal Dept Form, with the full menu structure, the global branding, the breadcrumbs etc. We do not want that, we want a simple, sober page with only the required details. Now we have two options: generate or create a Deptartment Details page specifically for this popup dialog window or modify the existing Dept.jspx to hide the unnecessary details, whenever the page is opened as dialog popup. In that case: how do we know or rather how does the page know it is opened in a dialog window. Let’s go for the second option and let’s use the processScope and a LaunchEvent to implement that dialog-awareness.

  1. First we need to create a managed bean that contains a LaunchListener, an event handling method that is invoked when our dialog window is launched. The method will not do much: only set a flag in processScope, to be inspected in any page that may find itself running inside a Dialog window:
    package nl.amis.view;

    import oracle.adf.view.faces.event.LaunchEvent;

    public class DialogHandler {
    public DialogHandler() {
    }

    public void handleDialogLaunch(LaunchEvent event) {
    event.getDialogParameters().put("inDialog","true");
    }
    }

  2. Configure this managed bean in the faces-config.xml file:
     <managed-bean>
    <managed-bean-name>DialogLaunchHandler</managed-bean-name>
    <managed-bean-class>nl.amis.view.DialogHandler</managed-bean-class>
    <managed-bean-scope>application</managed-bean-scope>
    </managed-bean>
  3. Add a launchListener to the CommandLink: launchListener="#{DialogLaunchHandler.handleDialogLaunch}" This will mean that whenever the commandLink is activated and a dialog window is opened, just beforehand the handleDialogLaunch method on the DialogLaunchHanlder managed bean is invoked – to do whatever it thinks should be done.
    <af:commandLink   useWindow="true" partialSubmit="true" 
    action="dialog:DeepLinkDept" id="EmpDname"
    text="#{bindings.EmpDname.inputValue}"
    launchListener="#{DialogLaunchHandler.handleDialogLaunch}"
    >
    <f:param name="deptno" value="#{bindings.EmpDeptno.inputValue}" />
    </af:commandLink>

  4. This particular method as we have seen sets a flag in the processScope that the Dept.jspx page can read and interpret. Most specifically: it can define rendered attributes using the value of the flag – inDialog – to show or hide menu-tabs, titles, global buttons etc. We can return now to the Depts.jspx page and make the display or hide of PanelGroup elements depend on #{processScope.inDialog==’true’}:

    For example:

    <af:panelPage  title="#{  createModes.CreateDept 
    ? nls['INSERT_TITLE_DEPT']
    : ( processScope.inDialog!= 'true'
    ? nls['EDIT_TITLE_DEP:#{bindings.DeptDname}']
    : nls['DETAILS_TITLE_DEP:#{bindings.DeptDname}']
    )}" >

    <f:facet name="brandingAppContextual">
    <af:region id="brandingAppContextual" rendered="#{processScope.inDialog!= 'true'}"
    regionType="oracle.jheadstart.region.brandingAppContextual"/>
    </f:facet>
    <f:facet name="branding">
    <af:region id="branding" rendered="#{processScope.inDialog!= 'true'}"
    regionType="oracle.jheadstart.region.branding"/>
    </f:facet>
    <f:facet name="menuGlobal">
    <af:region id="menuGlobal" rendered="#{processScope.inDialog!= 'true'}"
    regionType="oracle.jheadstart.region.menuGlobal"/>
    </f:facet>

    <f:facet name="location">
    <af:menuPath var="bc" value="#{jhsBreadcrumbStack}" rendered="#{processScope.inDialog!= 'true'}">
    <f:facet name="nodeStamp">
    <af:commandLink action="#{bc.goToDestination}" text="#{bc.label}"
    immediate="true" onclick="return alertForChanges();">
    <f:actionListener type="oracle.jheadstart.controller.jsf.listener.DoRollbackActionListener"/>
    <af:resetActionListener/>
    </af:commandLink>
    </f:facet>
    </af:menuPath>
    </f:facet>

    <f:facet name="menu1">
    <af:region id="AppModuleMenu1Tabs" value="#{bindings}"
    regionType="view.region.AppModuleMenu1Tabs"
    rendered="#{processScope.inDialog!= 'true'}">
    <af:attribute name="selectedTab" value="Dept"/>
    </af:region>
    </f:facet>
    ...

    <af:panelButtonBar rendered="#{processScope.inDialog!= 'true'}">

    ...

  5. To support an NLS enabled title for this Details Lookup Dialog Window, I have added the following entry to the ApplicationResources.properties Resource Bundle:
    DETAILS_TITLE_DEP=Inspect the details for Department {0}
  6. We also need to provide a way to Close the Dialog Window – via a Close button seems appropriate:
    <af:panelGroup rendered="#{processScope.inDialog== 'true'}" > 
    <af:commandButton text="Close" immediate="true">
    <af:returnActionListener />
    </af:commandButton>
    </af:panelGroup>
  7. Re-run the application – the Emp.jspx page – and open the dialog window with additional Department details.
    Show lookup details in popup (dialog) window using ADF Faces & JHeadstart 10.1.3 deepCopyDialogRefined

Resources

Download the JDeveloper 10.1.3 Application (note: in order to run the application, you need to install the JHeadstart 10.1.3 Runtime Environment; also note that the files adf-faces-impl.jar and jsf-impl.jar should be copied to the public-html/WEB-INF/lib directory) JHeadstartEmpDept.zip.

ADF Developer’s Guide for Forms/4GL Developers, specifically chapter 19 on Using Popup Dialogs

JHeadstart 10.1.3 Developer’s Guide (preview) – not publicly available. 

One Response

  1. Ramu October 16, 2006