vrijdag 4 maart 2011

How to create a custom LOV

Technology: ADF11g
Developed in: JDeveloper 11.1.1.3.0
Browsers tested: Firefox 3.6.13 and Internet explorer 7 (7.0.6002.18005)
Used database schema: HR
Used tables: EMPLOYEES, DEPARTMENTS, LOCATIONS


Summary

In this blog we create ‘standard’ LOVs and a custom LOV. A custom LOV is in the end created because of some disadvantages I see in the standard LOVs like:
  • Possibility to resize LOV popup
  • All columns in the LOV table have the same width

Standard LOV

First we’ll create a standard LOV. With a standard LOV I mean a LOV defined in the view object as a List of Values on the ID column.

For this example the EMPLOYEES table is used with LOVs on the ManagerId attribute and DepartmentId attribute (the DepartmentId LOV is created in the next paragraph).

Model layer

Create the following entities:

Entity name Based on table of HR schema Customizations made
Employee EMPLOYEES None


Create the following view objects:

View object name Based on entities Customizations made
EmployeesLovView Employee None
ManagersView Employee None


Open the EmployeesLovView and go to the ManagerId attribute. Add a List of Values:



The ManagersView is the view accessor (renamed to ManagersAccessor), the view attribute is the ManagerId and the list attribute the EmployeeId. On the UI Hints tab set the following properties:

Property Value
Default List Type Input Text with List of Values
Display Attributes Select all
List Search <No Search>
"Include No Selection" Item Deselect all


Create an application module HrAppModule which exposes the EmployeesView.

Page

A form page is created by drag and drop from the Data Controls. The form is dropped as ADF Form only the EmployeeId, FirstName, LastName, JobId and ManagerId items are displayed. All items except ManagerId are displayed as Output text with label. ManagerId is displayed as input list of values:





Select Include Navigation Controls and Include Submit Button.

If we run this page it looks like this:



The opened popup contains scrollbars and is not resizable. When a row is selected (by double click or by using the OK button) the ID of the employee is copied to the ManagerId attribute.

Extended standard LOV

The first thing I thing needs to be changed is that the ManagerId is displayed. I think the managers name is a more desirable field to see (of course in the database the manager ID should be filled).

To create an example to show how this can be achieved another LOV is created for the department. In the screen we’ll display the department name and the LOV is on this name but the department ID is filled as well (to prove this the department ID will be made visible but read only in the page).

Model layer

Create the following entities:

Entity name Based on table of HR schema Customizations made
Department DEPARTMENTS None
Location LOCATIONS None


A FK association will be created at the same time between Department and Location.

Create the following view objects:

View object name Based on entities Customizations made
DepartmentsLocationView Department

Location
None


Change the EmployeesLovView:
  • Add a transient attribute DepartmentLovName of type String
  • Make the attribute always updatable
  • Check the Mapped to Column or SQL checkbox
  • Fill the expression of the Query Column:
    • (SELECT department_name FROM departments WHERE department_id = Employee.department_id)
  • Set the type of the Query Column to VARCHAR2(30)


The last 3 steps are necessary to display the current department name when the page is opened.
  • Add a List of Values to the DepartmentLovName attribute:


The DepartmentsLocationView is the view accessor (renamed to DepartmentsLocationAccessor), the view attribute is the DepartmenLovName and the list attribute the DepartmentName.

Add a second return value from DepartmentId to DepartmentId:



On the UI Hints tab set the following properties:

Property Value
Default List Type Input Text with List of Values
Display Attributes Select all
List Search <No Search>
"Include No Selection" Item Deselect all



Page

Drop the DepartmentId and DepartmentLovName attribute from the Data Controll palette onto the page created for the Manager LOV. The DepartmentId is displayed as Output text with label, the DepartmentLovName as Input list of values.

If we run this page it looks like this:



When a row is selected (by double click or by using the OK button) the Name and the ID of the department is copied to the page. That is an improvement compared to the Manager ID. But the opened popup still contains scrollbars and is not resizable.

Create a custom (resizable) LOV

Finally we’ll create a resizable LOV. This is also done for the department.

Model layer

Change the EmployeesLovView (make a copy of DepartmentLovName):
  • Add a transient attribute DepartmentLovName2 of type String
  • Make the attribute always updatable
  • Check the Mapped to Column or SQL checkbox
  • Fill the expression of the Query Column:
    • (SELECT department_name FROM departments WHERE department_id = Employee.department_id)
  • Set the type of the Query Column to VARCHAR2(30)

Page

Drop the DepartmentId (same as used for the department LOV) and DepartmentLovName2 attribute from the Data Controll palette onto the page underneath a seperator. The DepartmentId is displayed as Output text with label, the DepartmentLovName2 as Input text with label.

Surround the DepartmentLovName2 input text in a panelGroup with layout style horizontal. After the input text add a command image link with the LOV icon. The command link triggers a popup:

<af:panelGroupLayout id="lovGroup"

layout="horizontal">

<af:inputText value="#{bindings.DepartmentLovName21.inputValue}"

label="#{bindings.DepartmentLovName21.hints.label}"

required="#{bindings.DepartmentLovName21.hints.mandatory}"

columns="#{bindings.DepartmentLovName21.hints.displayWidth}"

maximumLength="#{bindings.DepartmentLovName21.hints.precision}"

shortDesc="#{bindings.DepartmentLovName21.hints.tooltip}"

id="departmentLovNameInputText">

<f:validator binding="#{bindings.DepartmentLovName21.validator}"/>

</af:inputText>

<af:commandImageLink id="departmentLovNameCommandLink"

icon="/common/images/lov.png">

<af:showPopupBehavior popupId="departmentLovPopup"

triggerType="action"/>

</af:commandImageLink>

</af:panelGroupLayout>

The picture (lov_ena.png) can be copied from:
  • Run your application, in the IntegratedWebLogicServer log you see a destination where the EAR is copied to. On my computer is that:
    • [03:25:38 PM] Wrote Web Application Module to C:\Users\mhorsch\AppData\Roaming\JDeveloper\system11.1.1.3.37.56.60\o.j2ee\drs\HR_demo_app\ViewControllerWebApp.war
  • Go to the o.j2ee folder and in that folder go to: \.wlLibs\jsp
  • Open the ADF-Faces-Components11.war
  • Go to \WEB-INF\lib and open the adf-richclient-impl-11.jar jar file
  • Go to adf\images
The popup only contains the DepartmentsLocationView as read only table. First create the popup:

<af:popup id="departmentLovPopup">

<af:dialog id="lovDialog"

title="LOV"

type="okCancel"

dialogListener="#{employeeBean.lovDialogListeners}"

resize="on"

contentWidth="600"

stretchChildren="first">

</af:dialog>

</af:popup>

This popup is 600 pixels width by default and resizable. If the dialog is closed lovDialogListeners of the employeeBean is called.

This bean class is defined in the unbound task flow:

Managed bean property Value
Name employeeBean
Class nl.hr.demo.view.beans.EmployeeBean
Scope request


The DepartmentsLocationView table is inserted in the dialog by drag and drop from the data control palette:





The Row Selection property must be checked, this causes the following properties to be set in the table:

Property Value
selectedRowKeys #{bindings. DepartmentsLocationView.collectionModel.selectedRow}
selectionListener #{bindings. DepartmentsLocationView.collectionModel.makeCurrent}
rowSelection single


Although in the JSPX page the selectedRowKeys and selectionListener statements contains warnings that the references methods cannot be found they can be found runtime.

In the EmployeeBean we have to implement the lovDialogListeners method. The method is only executed when the LOV is closed by the OK button. In the method the department ID and name of the selected row are copied to the EmployeesLovView row:

package nl.hr.demo.view.beans;



import javax.faces.context.FacesContext;

import nl.hr.demo.model.services.HrAppModuleImpl;

import oracle.adf.model.binding.DCBindingContainer;

import oracle.adf.model.binding.DCDataControl;

import oracle.adf.view.rich.event.DialogEvent;

import oracle.binding.BindingContainer;

import oracle.jbo.domain.Number;

import oracle.jbo.server.ViewRowImpl;



public class EmployeeBean {

public EmployeeBean() {

super();

}



private static HrAppModuleImpl getService() {

DCBindingContainer bc = (DCBindingContainer)FacesContext.getCurrentInstance().getApplication().evaluateExpressionGet(FacesContext.getCurrentInstance(), "#{bindings}", BindingContainer.class);

DCDataControl dc = bc.findDataControl("HrAppModuleDataControl");

return (HrAppModuleImpl) dc.getDataProvider();

}



public void lovDialogListeners(DialogEvent dialogEvent) {

ViewRowImpl row = (ViewRowImpl)getService().getDepartmentsLocationView().getCurrentRow();

if (row != null) {

Number departmentId = (Number) row.getAttribute("DepartmentId");

String departmentName = (String)row.getAttribute("DepartmentName");

ViewRowImpl employeeRow = (ViewRowImpl)getService().getEmployeesLovView().getCurrentRow();

employeeRow.setAttribute("DepartmentId", departmentId);

employeeRow.setAttribute("DepartmentLovName2", departmentName);

}

}

}

If we run this page it looks like this:



The popup is resizable, the name and id are copied and refreshed and the width of each column can be modified individually (by setting the width property of the af:column).

1 opmerking:

  1. thankz for posting this topic,,
    i have already search this topic from a month ago,,
    and i find in your blog,,

    thank you,,

    Keep Posting ya ^__^

    BeantwoordenVerwijderen