Education

NEOS offers a range of training courses across Java and Oracle’s ADF technologies. From “boot camps” that teach you product basics in several intensive days, to sets of courses that take trainees step by step through a complete product learning path – our training courses equip you and your team to deliver effective Oracle ADF projects.

Our courses cover more details, have excellent grounding in real-world project issues, and are usually more cost effective. In addition, as we develop our own course materials, we can also customize content to meet particular needs and requirements.

Our expert consultants ensure that courses and techniques you learn from us are based on years of real-world project experience.

Contact Us

Whether you're looking for answers, would like to
solve a problem contact us right here.

Customize your Auto Suggest behavior List of Values

  • Posted on: November 11, 2016

Customizing input components to improve user experience is useful and, in most cases, necessary. Several interesting concepts for customization of list of values using auto suggest behavior are explored in this blog post.

Introduction

Using List of Values in conjunction with Auto Suggest Behavior is a common practice, but their customization has a couple of quirks that may deter you from using them. The following topics are explored in this blog post:

  • Auto Suggest Behavior list customization
  • Creating and changing View Criteria programmatically

Examples in this blog post are tied to the default HR schema found in Oracle XE.

Components

The simplest use case that showcases everything mentioned in the introduction is a .jsf page with following page code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<!--?xml version='1.0' encoding='UTF-8'?-->
<!DOCTYPE html>
<f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
   <af:document title="KickStartAutoSuggest.jsf" id="d1">
       <af:messages id="m1"/>
       <af:form id="f1">
           <af:panelFormLayout id="pfl1" maxColumns="2">
               <f:facet name="footer"/>
           </af:panelFormLayout>
           <af:panelGroupLayout id="pgl1" layout="horizontal">
               <af:inputComboboxListOfValues id="jobTitleId"
                                             popupTitle="Search and Select: 
                                                         #{bindings.JobTitle.hints.label}"
                                             value="#{bindings.JobTitle.inputValue}"
                                             label="#{bindings.JobTitle.hints.label}"
                                             model="#{bindings.JobTitle.listOfValuesModel}"
                                             required="#{bindings.JobTitle.hints.mandatory}"
                                             columns="#{bindings.JobTitle.hints.displayWidth}"
                                             shortDesc="#{bindings.JobTitle.hints.tooltip}"
                                             binding="#{AutoSuggestBean.autoSuggestComponent}"
                                             partialTriggers="b1"
                                             searchDialog="none"
                                             autoSubmit="true"
                                             autoTab="true">
                   <f:validator binding="#{bindings.JobTitle.validator}"/>
                   <af:autoSuggestBehavior
                                   maxSuggestedItems="-1"
                                   suggestedItems="#{AutoSuggestBean.customSuggestedItems}"/>
               </af:inputComboboxListOfValues>
               <af:spacer width="10"
                          height="10"
                          id="s1"/>
               <af:button text="Remove"
                          id="b1"
                          actionListener="#{AutoSuggestBean.removeSelectedFromList}"/>
           </af:panelGroupLayout>
       </af:form>
   </af:document>
</f:view>

Result of above code is shown in Figure 1 – Page Components.

result_1

Figure 1 – Page Components

The “JobTitle” combo box with list of values is bound to an entity-based view object JobsVO with JobTitleLOV set as a List of Values parameter of the JobTitle attribute. Figure 2 – JobsVO View Object Attributes shows Attribute List and Attribute on which List of Values is applied while Figure 3 – List of Values definition shows how the List of Values is bounded with the specific Attribute.

editor_1_1

Figure 2 – JobsVO View Object Attributes

editor_2

Figure 3 – List of Values Definition

In order to do sorting of data on specific List of Values defined for specific View Object, and at the same time avoid doing sorting globally for List of Values and all its references View Accessor of View Object should be accessed and edited as in Figure 4 – Sorting View Accessor. In same way default View Criteria, Parameter Values and event Tuning can be achieved for specific View Accessor.

editor_3

Figure 4 – Sort of View Accessor

af:inputComboboxListOfValues’ dropdown menu shows all available JobTitleLOV members. Usage is displayed in following Figure 4 – Dropdown List

editor_4

Figure 5 – Dropdown List

af:autoSuggestBehavior shows the JobTitleLOV members that contain the string user has inputted. Usage is presented in Figure 4 – Auto Suggest Behaviour. That behavior is customizable and explained in this blog post.

editor_5

Figure 6 – Auto Suggest Behavior

 

af:button “Remove” is the main focus of this blog post. It removes the currently selected value from both the af:inputComboboxListOfValues and the af:autoSuggestBehavior by constructing and applying custom view criteria programmatically. It can be used multiple times to remove multiple values.

Implementation

Auto Suggest Behavior list customization
af:autoSuggestBehavior’s backing bean method is shown below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public List customSuggestedItems(String string) {
// getting the view object
AppModuleImpl am = getAppModule();
JobsVORowImpl vr = (JobsVORowImpl) am.getJobsVO1().getCurrentRow();
RowSet rs = vr.getJobTitleLOV1();
JobTitleLOVImpl jo = (JobTitleLOVImpl) rs.getViewObject();
 
// filtering view object's rows and generating a suggested item list
Row[] rows = jo.getAllRowsInRange();
String title = "";
List l = new ArrayList();
for (Row r : rows) {
title = r.getAttribute("JobTitle").toString();
if (title.toUpperCase().contains(string.toUpperCase())) {
SelectItem si = new SelectItem();
si.setLabel(title);
si.setValue(title);
l.add(si);
}
}
return l;
}

Backing bean code is split into two main parts. The first part of the code gets the view object containing the list of values we want to use for the autosuggest behavior. The second part of the code simply filters all rows by comparing them to the string parameter (string parameter contains the value user has entered in the combo box). The simplest way to customize its behavior is to alter the “if” statement at line 49. The List should contain all values that will be presented to the user when they enter a String s value into the combo box.
NOTE: be vary of executing queries in this method because it executes each time a new character is entered into the combo box so it could be wise to consider a length of user input so that query will be executed after certain number of characters has been entered.

Creating and changing custom view criteria programmatically
The first step in creating and applying custom view criteria programmatically is creating a method in the application module implementation class. In this example, we will create view criteria that act like a dynamic SQL where clause with “NOT IN” operator and excludes any number of values from our list of values view object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public void updateViewAccessor1(String s) {
    // getting the current view criteria
    JobsVORowImpl cro = (JobsVORowImpl) this.getJobsVO1().getCurrentRow();
    JobTitleLOVImpl clov = (JobTitleLOVImpl) cro.getJobTitleLOV1().getViewObject();
    ViewCriteria vco = clov.getViewCriteria("showCaseViewCriteria");
 
    // initial parameter, used only during first execution
    String newParameters = "'" + s + "'";
 
    // if view criteria already exists, find old parameters and append the new one
    if (vco != null) {
        List l = vco.getRows();
        Iterator i = l.iterator();
        while (i.hasNext()) {
            Row r = (Row) i.next();
            String viewCriteria = r.getAttribute(JobTitleLOVRowImpl.JOBTITLE).toString();
            String oldParameters =
                viewCriteria.substring(viewCriteria.indexOf("(", 1) + 1, viewCriteria.indexOf(")", 1));
            newParameters = oldParameters + ",'" + s + "'";
        }
    }
 
    // create the view criteria, apply it and execute query
    ViewCriteria vc = clov.createViewCriteria();
    vc.setName("showCaseViewCriteria");
    ViewCriteriaRow vcr = vc.createViewCriteriaRow();
    vcr.setAttribute(JobTitleLOVRowImpl.JOBTITLE, "NOT IN (" + newParameters + ")");
    vc.addElement(vcr);
    clov.applyViewCriteria(vc);
    clov.executeQuery();
}

In this case, the method takes a single parameter that is used for adding new values to the exclusion list. The exclusion list contains all values that we wish to exclude from combo box and auto suggest components. The following steps are implemented for achieving the desired behavior. First – getting the current state of the custom view criteria (named “showCaseViewCriteria”). Then, if that view criteria exist, reading the old parameter list from it (e.g. “’Manager’,’Accountant’”). After reading the old parameter list, the value from the String s parameter is appended to the list (e.g. “’Manager’,’Accountant’,’President’”). After the exclusion list has been modified, new custom view criteria is created, applied to the view object and its query is executed.

The final step in achieving the desired behavior is binding an action listener method to the “Remove” button.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void removeSelectedFromList(ActionEvent actionEvent) {
    // getting the currently selected value and adding it to view criteria
    String currentlySelected = this.getAutoSuggestComponent().getValue().toString();
    getAppModule().updateViewAccessor1(currentlySelected);
 
    // removing the currently inputed text
    this.getAutoSuggestComponent().setValue("");
 
    // refreshing the dropdown list in the combo box
    AppModuleImpl am = getAppModule();
    JobsVOImpl vo = (JobsVOImpl)am.getJobsVO1();
    JobsVORowImpl vr = (JobsVORowImpl) vo.getCurrentRow();
    RowSet rs = vr.getJobTitleLOV1();
    JobTitleLOVImpl voi = (JobTitleLOVImpl) rs.getViewObject();
    voi.clearCache(); 
}

The method shown above can be divided into three main parts as shown in the code comments. First part gets the currently selected value from the combo box component and calls the method that adds it to the exclusion list. Secondly, the box input field is emptied to indicate that the desired effect is achieved. The final part of this method clears cache to force af:ComboboxListOfValues component to update its dropdown list.

Conclusion

While the example shown in this blog post is very simple, this approach can be used to achieve the desired behavior in much more complex situations. Combo boxes and auto suggest behavior are an attractive combination because they are intuitive, quick and appealing to both new and experienced users. Applying the customizations described in this blog post can make them more convenient and more powerful.

You can download this demo project here.