Oracle® Application Development Framework Developer's Guide
10g Release 3 (10.1.3) B25386-01 |
|
![]() Previous |
![]() Next |
The selectManyShuttle
and selectOrderShuttle
components render two list boxes, and buttons that allow the user to select multiple items from the leading (or "available") list box and move or shuttle the items over to the trailing (or "selected") list box, and vice versa. Figure 11-22 shows an example of a rendered selectManyShuttle
component. You can specify any text you want for the headers that display above the list boxes.
Note: In addition to using the supplied Move and Remove buttons to shuttle items from one list to the other, you can also double-click an item in either list. Double-clicking an item in one list moves the item to the other list. For example, if you double-click an item in the leading list, the item is automatically moved to the trailing list, and vice versa. |
The only difference between selectManyShuttle
and selectOrderShuttle
is that in the selectOrderShuttle
component, the user can reorder the items in the trailing list box by using the up and down arrow buttons on the side, as shown in Figure 11-23.
In the SRDemo application, the SRSkills page uses a selectManyShuttle
component to let managers assign product skills to a technician. Figure 11-24 shows the SRSkills page created for the sample application. The leading list box on the left displays products such as washing machines and dryers; the trailing list box on the right displays the products that a technician is skilled at servicing.
To review and change product skill assignments, a manager first selects a technician's name from the dropdown list above the shuttle component. The application then displays the technician's existing skill assignments in the trailing list, as shown in Figure 11-25.
Below the leading and trailing lists are optional boxes for displaying a description of a product. To view a description of a product, the manager can select an item from either list box, and the application displays the product's description in the box below the list.
To add new skill assignments, the manager selects the products from the leading list (Available Products) and then clicks the Move button.
To remove skills from the Assigned Skills list, the manager selects the products from the trailing list and then clicks the Remove button.
Like other ADF Faces selection list components, the selectManyShuttle
component can use the f:selectItems
tag to provide the list of items available for display and selection in the leading list.
Before you can bind the f:selectItems
tag, create a class that maintains a list of the valid products (skills) for the shuttle, and the indexes of the products that are assigned to (selected for) a technician. The class should use the page's binding container to get the product master list for populating the shuttle's leading list. Example 11-59 shows the SkillsHelper
class that is created to manage the population and selection state of the shuttle component on the SRSkills page.
Example 11-59 SkillsHelper Class
package oracle.srdemo.view; import java.util.ArrayList; import java.util.HashMap; import java.util.List; ... public class SkillsHelper { private BindingContainer bindings; private List<Product> productMasterList; private List <SelectItem> allProducts; private HashMap productLookUp; private int[] selectedProducts; private int skillsFor; private boolean skillsChanged = false; public List<SelectItem> getAllProducts() { if (allProducts == null) { OperationBinding oper = getBindings().getOperationBinding("findAllProduct"); productMasterList = (List<Product>)oper.execute(); int cap = productMasterList.size(); allProducts = new ArrayList(cap); productLookUp = new HashMap(cap); //for(Product prod: products) { for (int i=0;i<cap;i++){ Product prod = productMasterList.get(i); SelectItem item = new SelectItem(i, prod.getName(),prod.getDescription()); allProducts.add(item); productLookUp.put(prod.getProdId(), i); } } return allProducts; } public void setAllProducts(List<SelectItem> allProducts) { this.allProducts = allProducts; } public void setSelectedProducts(int[] selectedProducts) { skillsChanged = true; this.selectedProducts = selectedProducts; } public int[] getSelectedProducts() { Integer currentTechnician = (Integer)ADFUtils.getBoundAttributeValue(getBindings(),"currentTechnician"); if (currentTechnician != null){ if (skillsFor != currentTechnician.intValue()){ skillsFor = currentTechnician.intValue(); skillsChanged = false; OperationBinding getAssignedSkillsOp = getBindings().getOperationBinding("findExpertiseByUserId"); List<ExpertiseArea> skills = (List<ExpertiseArea>)getAssignedSkillsOp.execute(); selectedProducts = new int[skills.size()]; for (int i=0;i<skills.size();i++){ Integer lookup = (Integer)productLookUp.get(skills.get(i).getProdId()); selectedProducts[i] = lookup.intValue(); } } } return selectedProducts; } public List<Integer> getSelectedProductIds(){ ArrayList prodIdList = new ArrayList(selectedProducts.length); for (int i:selectedProducts){ prodIdList.add(productMasterList.get(i).getProdId()); } return prodIdList; } public void setBindings(BindingContainer bindings) { this.bindings = bindings; } public BindingContainer getBindings() { return bindings; } public void setSkillsChanged(boolean skillsChanged) { this.skillsChanged = skillsChanged; } public boolean isSkillsChanged() { return skillsChanged; } }
The methods of interest in the SkillsHelper
class are getAllProducts()
and getSelectedProducts()
.
The getAllProducts()
method is the method that populates the shuttle's leading list. The first time this method is called, the findAllProduct()
method on the SRPublicFacade
session bean is invoked, and the list of products is cached in an array list of SelectItem
objects. The getAllProducts()
method also maintains a hashmap that enables reverse lookup of the list item index number based on the product ID.
The getSelectedProducts()
method returns an array of int
values, defining the list of items that appear on the shuttle's trailing list. This method also checks whether the currently selected technician (from the dropdown list above the shuttle) has changed. If the currently selected technician has changed, the findExpertiseByUserId()
method on the SRAdminFacade
session bean is invoked, and the new current technician's list of skills is retrieved and displayed in the trailing list of the shuttle.
The SkillsHelper
class is maintained as a session
scoped managed bean named skillsHelper
. Example 11-60 shows the managed beans configured for working with the shuttle component in the SRDemo application.
Example 11-60 Managed Beans for the Shuttle Component in the faces-config.xml File
<managed-bean> <managed-bean-name>skillsHelper</managed-bean-name> <managed-bean-class>oracle.srdemo.view.SkillsHelper</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> <managed-property> <property-name>bindings</property-name> <value>#{data.SRSkillsPageDef}</value> </managed-property> </managed-bean> <managed-bean> <managed-bean-name>backing_SRSkills</managed-bean-name> <managed-bean-class>oracle.srdemo.view.backing.SRSkills</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean>
All the bindings of the SRSkills page are defined in the file app_management_SRSkillsPageDef.xml
, a reference of which is injected into the SkillsHelper
class. Example 11-61 shows the page definition file for the SRSkills page.
Example 11-61 Page Definition File for the SRSkills Page
<?xml version="1.0" encoding="UTF-8" ?> <pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel" version="10.1.3.36.2" id="SRSkillsPageDef" Package="oracle.srdemo.view.pageDefs"..> <executables> <methodIterator id="findAllStaffIter" Binds="findAllStaff.result" DataControl="SRPublicFacade" RangeSize="-1" BeanClass="oracle.srdemo.model.entities.User"/> <methodIterator id="findAllProductIter" Binds="findAllProduct.result" DataControl="SRPublicFacade" RangeSize="-1" BeanClass="oracle.srdemo.model.entities.Product"/> <variableIterator id="variables"> <variable Name="selectedStaffIdVar" Type="java.lang.Integer"/> </variableIterator> </executables> <bindings> <methodAction id="findAllStaff" InstanceName="SRPublicFacade.dataProvider" DataControl="SRPublicFacade" MethodName="findAllStaff" RequiresUpdateModel="true" Action="999" ReturnName="SRPublicFacade.methodResults.SRPublicFacade_dataProvider_findAllStaff_result"/> <methodAction id="findAllProduct" InstanceName="SRPublicFacade.dataProvider" DataControl="SRPublicFacade" MethodName="findAllProduct" RequiresUpdateModel="true" Action="999" ReturnName="SRPublicFacade.methodResults.SRPublicFacade_dataProvider_findAllProduct_result"/> <attributeValues IterBinding="variables" id="currentTechnician"> <AttrNames> <Item Value="selectedStaffIdVar"/> </AttrNames> </attributeValues> <methodAction id="findExpertiseByUserId" InstanceName="SRAdminFacade.dataProvider" DataControl="SRAdminFacade" MethodName="findExpertiseByUserId" RequiresUpdateModel="true" Action="999" ReturnName="SRAdminFacade.methodResults.SRAdminFacade_dataProvider_findExpertiseByUserId_result"> <NamedData NDName="userIdParam" NDType="java.lang.Integer" NDValue="#{bindings.currentTechnician.inputValue}"/> </methodAction> <list id="findAllStaffList" StaticList="false" ListOperMode="0" IterBinding="variables" ListIter="findAllStaffIter" NullValueFlag="1" NullValueId="findAllStaffList_null"> <AttrNames> <Item Value="selectedStaffIdVar"/> </AttrNames> <ListAttrNames> <Item Value="userId"/> </ListAttrNames> <ListDisplayAttrNames> <Item Value="firstName"/> <Item Value="lastName"/> </ListDisplayAttrNames> </list> <methodAction id="updateStaffSkills" InstanceName="SRAdminFacade.dataProvider" DataControl="SRAdminFacade" MethodName="updateStaffSkills" RequiresUpdateModel="true" Action="999"> <NamedData NDName="userId" NDValue="${bindings.currentTechnician.inputValue}" NDType="java.lang.Integer"/> <NamedData NDName="prodIds" NDValue="${skillsHelper.selectedProductIds}" NDType="java.util.List"/> </methodAction> </bindings> </pageDefinition>
The next procedure assumes you've already created the relevant bindings, a class similar to the SkillsHelper
class in Example 11-59, and configured the required managed beans in faces-config.xml
, as shown in Example 11-60.
To create a shuttle component:
From the ADF Faces Core page of the Component Palette, drag and drop SelectManyShuttle onto the page. JDeveloper displays the Insert SelectManyShuttle dialog, as illustrated in Figure 11-26.
Select Bind to list (select items) and click Bind... to open the Expression Builder.
In the Expression Builder, expand JSF Managed Beans > skills. Double-click allProducts to build the expression #{skillsHelper.allProducts}
. Click OK.
This binds the f:selectItems
tag to the getAllProducts()
method that populates the shuttle's leading list.
In the Insert SelectManyShuttle dialog, click Common Properties. Click Bind... next to the Value field to open the Expression Builder again.
In the Expression Builder, expand JSF Managed Beans > skills. Double-click selectedProducts to build the expression #{skillsHelper.selectedProducts}
. Click OK.
This binds the value
attribute of the selectManyShuttle
component to the getSelectedProducts()
method that returns an array of int
values, defining the list items on the shuttle's trailing list.
Example 11-62 shows the code for the selectManyShuttle
component after you complete the Insert SelectManyShutle dialog.
Example 11-62 SelectManyShuttle Component in the SRSkills.jspx File
<af:selectManyShuttle value="#{skillsHelper.selectedProducts}" ... <f:selectItems value="#{skillsHelper.allProducts}"/> </af:selectManyShuttle>
For more information about using the shuttle component, see the ADF Faces Core tags at
http://www.oracle.com/technology/products/jdev/htdocs/partners/addins/exchange/jsf/doc/tagdoc/core/index.html
When the SRSkills page is first accessed, the variable iterator executes and instantiates its variable, selectedStaffIdVar
. At this point, the variable does not contain a value. When the manager selects a name from the dropdown list, the variable is populated and the attribute binding can then provide the value for the findExpertiseByUserId()
method's parameter userIdParam
, using the EL expression for the value of the NamedData
Element.
When the Save skill changes command button (see Figure 11-24) is clicked, the current technician's user ID and the associated array of product IDs (assigned skills) are retrieved and sent to the updateStaffSkills()
method on the SRAdminFacade
bean.
Example 11-63 shows the code for the commandButton
component on the SRSkills.jspx
page.