This post shows how a selection in a list of value (LOV) can be used to navigate to another page to show detailed information about the selected item in the LOV. The sample uses the HR db schema, the work space can be loaded using the link provided at the end of the post.
Use Case
Using a af:selectOneChoice showing the department names of the departments table we want to select on department. Then by clicking a button we want to navigate to a different page which shows the details of the selected department.
Let’s start with a look at the finished application:
Running Application
After selecting a department from the af:selectOneChoice we see the index of the selected department.
Select Department
This is shown in the outputText below the LOV. Selection ‘Human Resources’ selects the index 3 in the LOV.
Navigate to Detail Page
And finally the detail Page where we see the correct department id for ‘Human Resources’ of 40.
Detail Page
Implementation
To implement this use case we define two view objects (VO). One which we use for the LOV of department names (DepartmentLOVView) and one which we use to show the detail on a form for the detail page (DepartmentView1).
Data Model
In the UI we define a bounded task flow (lov-select-detail-btf.xml) which is build using fragments. This task flow is put on a page (Start.jspx) as region.
lov-select-detail-btf
Before we begin to setup the LOV we need a place to store the selected value from the LOV. For this we create a pageDef file for the DepSelect.jsff by right clicking on the page and selecting ‘Go to Page Definition’ from the menu. As there is no pageDef file one is created for us. We define a variable DepId inside the variable section of the ‘Exceutables’ section. Then we add an attributeValue ‘DepId’ in the bindings section.
Define Variable DepId inside the Executables Section
Variable DepId
Add attributeValue Binding
Select DepId from variabels
To setup the LOV drag the DepartmentId from the DepaermentLOVView from the Data Controls section onto the DepSelecte.jsff fragment. Change the values in the dialog to match the image below:
Edit List Binding for DepartmentId
In the property editor for the selectOneChoice set the label property to ‘Depaertment’ and the value property to ‘#{bindings.DepId1.inputValue}’ which is the attribute we defined in the variables section. Set the autoSubmit property to true so that selected values are posted into the variable once the value changes. The final selectOneChoise code is
<af:selectOneChoice label="Department" id="soc1" required="#{bindings.DepartmentId.hints.mandatory}" value="#{bindings.DepId1.inputValue}"
autoSubmit="true" valuePassThru="true">
<f:selectItems value="#{bindings.DepartmentId.items}" id="si1"/>
</af:selectOneChoice>
To show the selected item we add an outputText which shows the “#{bindings.DepId1.inputValue}”, which is the place the value is stored after selecting a department in the LOV. Notice that we don’t see the DepartmentId (the PK of the VO), but the index of the selected department in the list binding. As we don’t use a value driven LOV we have to map the index back to the row key ourselves. One more reason to stick to model driven LOV whenever possible. In this use case we don’t use a model driven LOV by intent. This is to show how to map the index back to the row key of the list.
The missing element is a button we use to navigate to the next page, the detail page, showing the departments detail as a form (read only). To get this button, open the data controls section and then open the DepartmentsLOVView and open the ‘Operations’ node. Select the ‘setCurrentRowWithKeyValue’ operation and drag it onto the fragment. Drop it as operation->button. This will add the operation into the pageDef for the fragment. The image below shows the final pageDef:
Final pageDef
The missing part is the mapping of the selected index to the needed key of the department. For this we select the button, go to the properties of the button. In the action property we select ‘Edit’ from the drop down list (small arrow) on the right side of the property. In the Dialog we create a new bean ‘DepSelectBean’ in the package ‘de.hahn.blog.lovselectdetail.view.beans’. In the method part we choose ‘new’ to create a new method ‘showSelectedDep’. Finally we change over to the source tab of the fragment and delete the ‘#{bindings.setCurrentRowWithKeyValue.execute}’ from the actionListener property. The reason for this is that we execute the method from the bean after we got the real DepartmentId from the LOV. The magic is done in the action method ‘showSelectedDep()’ in the bean.
public String showSelectedDep() {
BindingContext lBindingContext = BindingContext.getCurrent();
BindingContainer bindings = lBindingContext.getCurrentBindingsEntry();
// get the list binding for the department lov
JUCtrlListBinding list = (JUCtrlListBinding)bindings.get("DepartmentId");
// get the selected index from the list which is stored in the DepId1 attribute
AttributeBinding attr = (AttributeBinding)bindings.getControlBinding("DepId1");
Integer selid = (Integer)attr.getInputValue();
// load the listdata
Object row = list.getDisplayData();
// get the selected row from the list
Row lFromList = (Row)list.getValueFromList(selid);
// from the row we get the PK the DepartmentId
Object lAttribute = lFromList.getAttribute("DepartmentId");
Number newVal = (Number)lAttribute;
_logger.info("Information: selected Department = " + newVal);
// get the MethodAction for setCurrentRowWithKeyValue
OperationBinding method = bindings.getOperationBinding("setCurrentRowWithKeyValue");
// set hte needed parameter as the department id
method.getParamsMap().put("rowKey", newVal);
method.execute();
// after execution check for errors
List errors = method.getErrors();
if (!errors.isEmpty()) {
Exception ex = (Exception)errors.get(0);
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, ex.getMessage(), "");
FacesContext.getCurrentInstance().addMessage(null, msg);
// keep on page in case of an error
return null;
}
// navigate to the next page
return "show";
}
This concludes the implementation. The workspace can be loaded from ADF EMG Samples Project. The sample uses the HR db schema and was developed using JDeveloper 11.1.1.6.0