Thursday, August 23, 2007

Duncan Again

Using the Value of an ADF List Binding
Written By Duncan Mills, Oracle CorporationJune, 2006
Using list bindings ADF makes it very easy to associate drop-down lists and radio groups with either static or dynamic sets of data. When a suitable attribute is bound by dragging from the Data Control Palette and dropping as "Single Selection" the user specifies the value that will be populated and the label to use on the list entries themselves.
Where things get slightly confusing with such bound list UIs is the matter of a developer's initial expectation as to how the list should work. Taking the example of the EMPLOYEES and DEPARTMENTS table from the HR demo schema. If the Employee DepartmentID attribute is bound as a list and populated from the DEPARTMENTS table, the natural assumption would be that the list is composed of a set of elements, each of which, has a DepartmentID value and a DepartmentName label, for example 10-Administration, 20-Marketing, 30-Purchasing ...80-Sales and so on.
With this assumption in mind, developers often make the mistake of treating the value of the list binding as one of these expected values and trying to write code or expressions based on that. For example the developer might decide to conditionally render the Commission field on the screen using an expression based on the value of the DepartmentId field. In the example of a JavaServer Faces UI this might look like the following:
However, the expected result is not achieved because that initial assumption about the "value" of the list binding is actually incorrect. ADF actually manages the selected value of the list item internally and the value that is exposed through the list binding itself is only the index number of the selection in the list. So in the above example, the evaluated value of bindings.EmployeesView1DepartmentId.inputValue will probably evaluate to 8 rather than 80, depending on the contents of the DEPARTMENTS table.
This article examines how you can access the true value of the selected list item or radio button directly from ADF.
Creating a Secondary Binding
The simplest way to gain direct access to the true value of an attribute that is populated from a list binding is to create a secondary value binding to the underlying data. This secondary binding can then be used within expressions to access the true value of the attribute. Reverting to the example of the DepartmentId field, here are the steps. This assumes that you have suitable collections of data defined, in this case we're using ADF Business Components with default view objects for EMPLOYEES and DEPARTMENTS. We also assume here that you have already bound the DepartmentId attribute of the Employees collection as a list (for example an af:selectOneChoice if using JSF)
Open the page that contains the list item if it is not already open, and select Go to Page Definition from the right-click menu.
In the Structure window, select the bindings node, and from the right-click menu choose Insert inside bindings attributeBindings.
The attribute Binding Editor will appear. From the drop down list labeled Select an Iterator, select the iterator that the form fields are based on i.e. the Employees in this case. Then select the DepartmentId attribute on the right hand side. The dialog should look like the following illustration:
OK the dialog and a new binding (in this case called simply DepartmentId) is created. The primary (list) binding for the DepartmentId attribute will be called something like EmployeesView1DepartmentId.. You might want to clarify the purpose of the secondary binding by selecting it in the Structure window and using the Property Inspector to change the Id property to something that describes its function, such as "DepartmentIdCurrentValue".
Now the secondary binding is created you can go ahead and use it in expressions, for example "#{bindings.DepartmentIdCurrentValue.inputValue =='80'}" and it will evaluate as expected. You can also use the binding in code for example:

AttributeBinding deptIdBinding = (AttributeBinding)getBindings().getControlBinding("DepartmentIdCurrentValue"); Number deptId = (Number)deptIdBinding.getInputValue();

The ability to specify multiple bindings against the same attribute provides the developer with a great deal of flexibility. This example of working with list bindings shows one common use of the technique, but it can also be used in alternative contexts such as combinations of table and attribute bindings for "Summary Table + Detail View" type UIs.

No comments:

Getting Ref of the View Object referenced by the current Iterator binding for One iterator page without knowing the name of the iterator

Getting Ref of the View Object referenced by the current Iterator binding for One iterator page without knowing the name of the iterator ...