Tuesday, January 1, 2008

Complex List-Of-Values (LOV) in Oracle ADF

My first post in 2008 :-)

Today I will explain how to develop LOV component with three dependent tables and to return a set of values from LOV to parent table. Sample application - LOVComplex.zip is based on HR schema, you can find it in Oracle XE database. However, custom VACATIONREQUESTS table is used as well, it is used to implement three dependent columns. You can find information about this table and needed scripts in my previous post - Three Dependent List Boxes in af:table Component.

The main problem I'm describing in this post is about how to return several values from LOV component and update parent table with selected values from backing bean.

In Model layer I have generated four Entity objects - Department, Employees, Locations and Vacationrequests. Four View objects are generated as well. In HrModule I have enabled dependency between three View objects by adding EmployeesView4 instance into DepartmentsView3 instance.

In View layer I have created two pages - main and lov. First page contains three dependent columns, values in those columns can be changed using LOV component. Second page provides LOV component - three dependent tables. Page flow for developed sample application:

Now I will describe in three steps, how LOV with three dependent tables works, how values from LOV are returned and how parent table is refreshed.

1. LOV - three dependent tables

Dependent tables I have created by generating Master Table - Detail Table components from Data Control. I have generated two such components. However, in second component I removed Master table and have wired Detail table Employees to Departments table from first Master Table - Detail Table component. I have wired it by setting AutoSubmit=true for af:tableSelectOne component in Departments table and by setting PartialTriggers=departments on Employees table.

2. LOV - Set button

Set button in LOV window have setButton_action() method binded. Also this button contains af:returnActionListener component, this component is used to close LOV window when Set button is pressed. Let's concentrate on setButton_action() method:

This method is invoked when Set button is pressed. Iterators of all three dependent tables are accessed here and Id's are retrieved. Retrieved Id's are stored in valueHolder managed bean.

3. Parent table - refreshOnReturn()

When values in LOV are selected and and LOV is closed, ReturnListener associated with LOV button in parent table is invoked. refreshOnReturn() method retrieves returned values stored in managed bean and sets those values for current row in table:

When new values are set - refreshCurrentPage() method is invoked, this method executes refresh for current page. To make it work, don't forget to put PartialSubmit=true on button that invokes LOV component.

All steps are described, now I will show how it works. Table contains three dependent columns - LocationId, DepartmentId and EmployeeId. Values for those columns are set using LOV component. Table:

We can select any row in this table we want to update and press LOV button - LOV component will be opened:

You can notice values I have selected in LOV - 1700, 30, 117. When Set button is pressed - row in parent table is updated with selected values:

When running sample application, don't forget to add adf-faces-impl.jar and jsf-impl.jar to application's WEB-INF\lib directory.


Anonymous said...

Hai Andrejus,
my question is something different from ur post subject.I want to display values from other field from a dependent table instead of just ids.
For example the parent table should show
instead of just ids.
I tried with changing query(select departmentname from department where departmentid=parenttable.departmentid) in view object
but some times it wont work correctly.
Is there any other way to achieve this functionality

Andrej Baranovskij said...

Hi Ans,

Yes its possible to do it in other way. You can just implement read-only af:selectOneChoice components in those columns you mentioned. So, label will be displayed, instead of Id.


Anonymous said...

Hai Andrejus,
I tried with ur suggestion.
But it shows an error like This.
oracle.adfinternal.view.faces.renderkit.core.xhtml.SimpleSelectOneRenderer _getSelectedIndex
WARNING: Could not find selected item matching value "1" in CoreSelectOneChoice[UIXEditableFacesBeanImpl, id=selectOneChoice4]

But the list contains a value for id 1

I tried with setting valuePassThru="true"
af:selectOneChoice,but no use.
Is anything else needed to get
the label
Please help me

Andrej Baranovskij said...

Hi Ans,

You can send me your application, I will take a look during week. It should work actually.


Anonymous said...

Hi Andrejus,

I am facing the same error as Ans i.e. I am getting Could not find selected item match value error. Could you please provide any pointers as to how you resolved the issue.