Using one ViewObject for Global Lookup Data (Part 3): Multi Language Support

In an earlier post I blogged about a how to use a DB table to hold look up data like gender, weekdays or title which can used in different locations as ‘List Of Value’ data (Using one ViewObject for Global Lookup Data (Part 2)).
This third part adds a use case where we add multi language support when we read data from the DB table. This is an enhancement of the use case implemented in part 2. The old use case could load data in one language only. Now we add the the language to the data in the db table to allow retrieval of language specific data.

To make the use case work, we add two columns to the existing table GENERALLOOKUP. The first one holds the language code and the second one an id which is unique in the type and language. We use this new id named ‘GROUPID’ in the LOV to show the data of the selected type.
The ‘GROUPID’ remains identical for each type and language so that we can enter data in different languages. For the language code we use the codes we get from a Locale class. A sample for the data of WEEKDAY Monday:

Sample for Multilanguage Entry

Sample for Multilanguage Entry

We start by changing the DB table GENERALLOOKUP we used in the sample introduced in part 2. The sql script setup_db_multilangual.sql which is part of the project workspace, adds the two mentioned columns. You find the link to download the workspace at the end of this post. The script holds the needed data for the multi language look up too.
The final DDL for the GENERALLOOKUP table is

  CREATE TABLE "GENERALLOOKUP" 
   (	
    "ID" NUMBER, 
	"TYPE" VARCHAR2(20 CHAR), 
	"DATA" VARCHAR2(255 CHAR), 
	"LANGUAGE" VARCHAR2(5 CHAR), 
	"GROUPID" NUMBER
   ) ;

Next we synchronize the existing EO with the new GENERALLOOKUP table to get the new attributes into the EO

Synchronize with DB

Synchronize with DB


Here are some of the dialogs which you see when synchronizing the DB to the business objects

Now we have to add the new columns to the VO as well

These changes now allow to use the VO GeneralLookup to select language dependent look up data from the db. We now a new view criteria, named TypeLookupByLanguageViewCriteria, to use the language information to only select data for one language and one type from the table.

This new view Criteria uses two bind variables to select only data of one type and one language. How to set these variables we see later in this post.
As we don’t want to break the old application we create a new VO based again on the existing Lookuptest entity object and name it ‘LookupMultiLanguageView’

Next step is to set up the LOVs accessors for the attributes WeekdayId, GenderIs, PositionId and TitleID. Here we only show how to do this for the WeekdayId attribute. The images below showing that we not only set the bindType to ‘WEEKDAY’, but the bindLanguage variable too. Here we use a groovy expression to get the current language from the current locale

The real work is done in pictures 3, 4, 5 and 6 where we use the view criteria we’ve build earlier (TypeLookupByLanguageViewCriteria) to select the type and language from the GeneralLookupView.
In Image 3 we use the GenerallookupView as view accessor for the weekdayId. We rename the accessor to WeekdayMultiLanguageLOV for better understanding what the view accessor does. As the WeekdayMultiLanguageLOV can select any type in any language, we have to use the view criteria and set its bind variables to only get the data we want. In this case we set the bindType variable to ‘WEEKDAY’ and the bindLanguage variable to the current language used in the browser. As this language can change, we can’t use a static string like we used for the bindType. The language has to be calculated. For this we use a groovy expression:

oracle.adf.share.logging.ADFLogger LOGGER = oracle.adf.share.logging.ADFLogger.createADFLogger(source.getClass()); 
loc = adf.context.locale; 
if (loc == null) {
  LOGGER.info("Language not set -> en");
  return 'en';
} else {
  lang = loc.language;
  shortLang = lang.substring(0,2);
  if (!"#de#it#fr#en#".contains(shortLang)) {
    LOGGER.info("Language not recognized -> en");
    shortLang="en";
  } else {
    LOGGER.info("Language set to -> "+lang.substring(0,2));
    shortLang = lang.substring(0,2);
  } 
}

Yes, you can do more with groovy then just simple calculations like “sal *12”!
We use groovy expression like a java function to get the locale from the AdfContext (groovy: loc = adf.context.locale;) and from the locale we get the language (groovy: lang = loc.language;). Now, there are some checks to make, like is the locale is set and if the language found is one of the languages we support. In this sample we only support ‘en’, ‘de’, ‘it’ and ‘fr’ but you can add other languages too. As the language we get from the locale can look like ‘en_US’ or ‘de_CH’ we only use the first two characters (groovy: shortLang = lang.substring(0,2);). You can even use a logger to print out information into the log.

We can now test the switching of languages in the application module tester. Before we start the tester we make sure we can change the locale in the tester. Open the menu ‘Tools’->’Preferences’ and select the node ‘Business Components’, then select the ‘Tester’ node where you can add different languages for the tester.

Supply Languages to Tester

Supply Languages to Tester


Running the tester

Please notice the log output which is visible below the tester which shows the groovy log messages.

Finally we adjust the UI by adding a new page MultiLanguageLookup and hook it up with the existing LookupTest page.

Setup New Test Page

Setup New Test Page


Then we need to setup the faces-config.xml to support multiple languages
Setup New Test Page

Setup New Test Page


Now, if we run the application and change the browser language, reload the page we see the language change

The sample used in this blog can be downloaded from the ADF-EMG Sample repository. The sample uses JDeveloper 11.1.1.7.0 and the HR DB schema.

Advertisements

Using one ViewObject for Global Lookup Data (Part 2)

Based on the other post ‘Using one ViewObject for Global Lookup Data’ I got an other question on how to use this approach in a way, that a LOV is initalized with an area of lookup data before the page in shown to the user.
This can be done, all declarative without the need to write java code e.g. in an onLoad() method. The solution is to use a bounded task flow which initializes the LOV before navigation to the page the LOV is used.
To show this we create a simple navigation model in the adfc-config.xml like

Navigation Model

Navigation Model

‘Generic Lookup’ is used to show how to do this inside a page, where the lookup is presented in a region, the ‘LookupInitPosition’ shows how to preset an area for the lookup data (POSITION in this case) before showing the page in a region too.
Before we go into detail on how to setup the UI we need to add another view object to our data model which we use the acquire the lookup data

VO to get Lookup Data

VO to get Lookup Data


The ‘GeneralLookup’ view object is the same we used in part 1 to get the lookup data of an area, only this time we don’t specify lookup area but a dummy value (‘1’ in this case) for the area. This dummy value is set so that we don’t get any result back. If the ‘GeneralLookup’ view is executed without an area given from the outside, we don’t get any result. Keep this in mind when we are looking at the running sample later on.

Back to the UI. As both use cases uses a region it’s a nice sample how a bounded task flow (btf) can be reused in different use cases. The bounded task flow itself looks like

Navigation Model Bounded Task Flow

Navigation Model Model Bounded Task Flow

Bounded Task Flow to Show preselected Lookup Data

Bounded Task Flow to Show preselected Lookup Data


As you see the bounded task flow uses a method call (ExecuteWithParams) as it’s start activity. A task flow parameter is used to pass the name of the lookup area we want the LOV to initially show.
The name of the input parameter does not really matter, what you have to note down is the value part ‘#{pageFlowScope.selectedType}’ as this is the the variable we use to set the bindType parameter of the method call activity ExecuteWithParams.

Setup of the ExecuteWithParams Method Call

Setup of the ExecuteWithParams Method Call

After executing the query with the new set bindType we navigate to to page to show the result:

Region View1 which shows the LOV with the Preselected Lookup Data

Region View1 which shows the LOV with the Preselected Lookup Data


We see the LOV as af:selectOneChoice which stores the selected value in an attribute from the variable iterator (see Creating Variables and Attribute Bindings to Store Values Temporarily in the PageDef for more info on this). The input text below the LOV can be used to change the area parameter used for the LOV. If we enter e.g. WEEKDAY and click the ‘Refesh’ button, the input value is read and transferred to the parameter (#{pageFlowScope.selectedType}) for the executeWithParameter method via a af:setPropertyListener. This allows to change the LOV on the fly from within the region.
The LOV source is a dynamic list generated from the Generallookup VO as seen in the next image
Setup LOV for af:selectOneChoice

Setup LOV for af:selectOneChoice

After we know how the region (the bounded task flow) works, we can build the GenericLookup.jspx page. This page allows to enter the name of an ares into an input text field and then to refresh the bounded task flow, which we put on the page as region.

The final use case is to navigate to a page with with a preselected lookup area, POSITION in this case. For this we use the button ‘goto Page with init on POSITION’ at the bottom of the page.

You can download the sample workspace which was build JDeveloper 11.1.1.7.0 and using the HR schema from the ADF EMG Samples side BlogStaticVOLov_V3.zip. You can open the workspace using JDev 11.1.1.6.0 without a problem. If you are asked if you like to migrate the workspace to 11.1.1.6.0 answer with Yes.

Using one ViewObject for Global Lookup Data

A user on the OTN JDeveloper & ADF forum asked how to use one ViewObject, which holds lookup data of different areads, as LOV source. This post shows how to do this.

UPDATE:
In part 2 I added a use case which shows how to use a global lookup view object to initialize a LOV component before a page loads and show the selected lookup data.

Before we begin we have to setup the data for the the sample we build to work with. For this we add two tables to the HR schema (or any other schema you have access to). One, GENERALLOOKUP, hols lookup data, which is grouped ba a type attribute.

General Lookup Data

General Lookup Data


As we see the type column is used to group the data into different areas. The task is to use one view object which queries this table as base for model driven LOVs. To show this we need another table which we use to enter values selected by a LOV for the area from the type column.
Test Table and Data

Test Table and Data

BlogGeneralLokup 018

Scripts to create the tables and insert some data into them are provided together with the sample workspace in the file ‘setup_db.sql’. After we setup the table and the data we create entity objects and view objects like we normally do. Once the eo and vo are created, we add a view criteria which we use to select a specific type of lookup data from the GENERALLOOKUP table.

ViewCriteria to Select Lookup Data

ViewCriteria to Select Lookup Data

The view criteria has one bind variable which we later use to distinguish the different groups of lookup data. Now we can setup the lov for the attributes of the LookupTestView view object. We show this for the TitleId attribute:

Setup LOV for  TitleId Attribute

Setup LOV for TitleId Attribute


Create LOV VO

Create LOV VO


BlogGeneralLokup 003 View Accessors
rename the view object to TiltelookupView andshuttle it to the selected area
Select the GeneralLookupView

Select the GeneralLookupView


Click the edit button on the top right
Edit the LOV View

Edit the LOV View


The vital part is that we switch to the ‘View Object’ node and select the view criteria ‘TypeLookupViewCriteria’ and set the bind variable to the desired type. In this case it is ‘TITLE’
BlogGeneralLokup 006 Edit View Accessor_ TitlelookupView

Select ViewCriteria and Bind Variable

Select ViewCriteria and Bind Variable

Once the list source is setup we select the id of the list source (TitlelookupView) as ‘List Attribute’ and set the TitleId as ‘View Attribute’ for the id. Finally select the ‘UI Hint’ tab and shuttle the ‘Data’ attribute to the ‘Selected’ side. The ‘Data’ attribute of the TitlelookupView will then shown in the listbox on the UI.
BlogGeneralLokup 008 Create List of Values

BlogGeneralLokup 009 Create List of Values

Setup LOV for TitleId

Setup LOV for TitleId

This concludes the implementation for the TitleId attribute. The other attributes (GenderId, PositionId and WeekdayId) are done hte same way. Only change the bind variable ‘bindType’ to the type area you are generating the LOV for.

The gallery above shows the running application. You can download the sample workspace which was build JDeveloper 11.1.1.7.0 and using the HR schema from the ADF EMG Samples side BlogStaticVOLov_V2.zip. You can open the workspace using JDev 11.1.1.6.0 without a problem. If you are asked if you like to migrate the workspace to 11.1.1.6.0 answer with Yes.

UPDATE:
In part 2 I added a use case which shows how to use a global lookup view object to initialize a LOV component before a page loads and show the selected lookup data.

JDeveloper 11.1.1.6.0 Use Selection in LOV to Navigate to Detail

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

Running Application

After selecting a department from the af:selectOneChoice we see the index of the selected department.

Select 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

Navigate to Detail Page

And finally the detail Page where we see the correct department id for ‘Human Resources’ of 40.

Detail Page

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

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

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

Define Variable DepId inside the Executables Section

Variable DepId

Variable DepId

Add attributeValue Binding

Add attributeValue Binding

Select DepId from variabels

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

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

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

JDeveloper 11.1.1.6.0: af:inputText with self made Look-Up not using LOV

In this blog entry shows how to setup an af:inputText with a look-up which gets its data from a db table for easy reference. This sounds like an af:inputListOfValues you might say. The difference is that an af:inputListOfValues validates the input against the data present in the DB. In case you want to allow the user to chose values available, but also allow adding values which are currently not present, you can’t use af:inputListOfValues.

After you drop a VO from the data control which has an attribute setup an attribute as InputListOfValue you get the following code:

                      <af:inputListOfValues id="emailId" popupTitle="Search and Select: #{bindings.Email.hints.label}" value="#{bindings.Email.inputValue}"
                                            label="#{bindings.Email.hints.label}" model="#{bindings.Email.listOfValuesModel}"
                                            required="#{bindings.Email.hints.mandatory}" columns="#{bindings.Email.hints.displayWidth}"
                                            shortDesc="#{bindings.Email.hints.tooltip}">
                        <f:validator binding="#{bindings.Email.validator}"/>
                      </af:inputListOfValues>

Now when we run the sample (which is build using the HR schema and JDev 11.1.1.6.0, source code available using the link provided at the end of the blog) we see the form like:

Running Application

Running Application

You can click on the magnifying glass to search for an existing value for the EMail attribute.

EMail Look Up

EMail Look Up

However, if we enter a value into the inputText which is not part of the LOV, we get an error

Error when Value isn't Part of the LOV

Error when Value isn’t Part of the LOV

One way to get around this is to delete the validator from the af:inputListOfValues. However, this means that no validations take place on this field. The idea of this post is to build the look-up part of the af:inputListOfValues our self and add it to an af:inputText. The look and feel remains the same:

Application with Self-made Look-UP

Application with Self-made Look-UP

As you see there is no difference on the first look. However, clicking the magnifying glass we get a slightly different look-up

Self-made Look-Up

Self-made Look-Up

Now we can enter any value into the EMail field without getting an error

EMail with 'new' Value

EMail with ‘new’ Value

How is this implemented?
In the model project we have two VOs: one fro the form (EmployeesView) and one for the EMail look-up (EmployeesEmailView). This second VO has a view criteria which we later use to build the look-up in the popup. A third VO in the model project (TestEmpView) is used to show the normal behavior of the EMail attribute with a LOV attached to it.

In the view controller project we have one start page (Page1) which hosts a panelTabbed for the different solutions. The self-made look-up is done in the bounded task-flow input-text-lookup-btf, which is dropped as region into the first tab. The region (input-text-lookup-btf.xml) is build by dragging the EmployeesView from the data control onto the fragment (test1.jsff) as ‘ADF Form’. To get the look & feel of the af:inputListOfValue we have add an icon behind the af:inputText. To make this possible we use an af:panelLabelAndMessage which shows the label for the EMail attribute. Inside this we place an af:inputText in simple format (otherwise the label would show up twice) and finally the icon for the look-up.

          <af:panelLabelAndMessage label="#{bindings.Email.hints.label}" id="plam1">
            <af:inputText value="#{bindings.Email.inputValue}" label="#{bindings.Email.hints.label}" required="#{bindings.Email.hints.mandatory}"
                          columns="#{bindings.Email.hints.displayWidth}" maximumLength="#{bindings.Email.hints.precision}"
                          shortDesc="#{bindings.Email.hints.tooltip}" id="it2" simple="true">
              <f:validator binding="#{bindings.Email.validator}"/>
            </af:inputText>
            <af:commandImageLink id="cil1" icon="/images/icon_Pruefen.gif" immediate="true" blocking="true">
              <af:showPopupBehavior popupId="p1" triggerType="action"/>
            </af:commandImageLink>
          </af:panelLabelAndMessage>

The generated af:inputText for the EMail attribute we simply delete. As you see the validator is still there but doesn’t show an error when we enter a value which is not part of the LOV from the popup. The popup used for the look-up, is a normal popup with a dialog as layout component. The dialog shows an af:query component generated by dragging the view criteria from the EmployeeEmailView from data control.

The missing part is how the value selected in the look-up is set into the EMail attribute on the form. This is done in the dialog listener which controls the dialog outcome:

    public void dialogListener(DialogEvent dialogEvent) {
        if (dialogEvent.getOutcome().equals(DialogEvent.Outcome.ok)) {
            // get the binding container
            BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
            // get an ADF attributevalue from the ADF page definitions
            AttributeBinding attr = (AttributeBinding)bindings.getControlBinding("EmailPopup");
            Object inputValue = attr.getInputValue();
            // set the value into the other attribute
            attr = (AttributeBinding)bindings.getControlBinding("Email");
            attr.setInputValue(inputValue);
        }
    }

The second tab (Test) hosts the normal use case using a af:inputListOfValue on the EMail attribute. This is just for reference.

The source for the sample can be loaded from GitHub. The sample is build on the HR db schema using JDeveloper 11.1.1.6.0.

JDeveloper: Using Static ViewObjects for Lookup Data used by e.g. LOV

This blog shows how to set up a static ViewObject in a model project and use this static data as lookup data in an other ViewObject as LOV. Static lookup data can and should be put into a shared application module, as the data seldom change during the live of the application using the static data. This we’ll leave for another blog. Here we create a model project and create a simple static ViewObject which we then use in another as choice list.
The sample was build using JDeveloper 11.1.1.6.0 and uses the HR schema. To get the workspace use the link provided at the end of this blog.

Use case:
We need some static data as lookup for an other attribute which resides in a view object. In this sample we use the COUNTIRES table from the HR schema which has an foreign key RegionId to the REGIONS table from the HR schema. Instead of using the REGIONS data directly, we setup a static view Object which holds the data to be shown for the foreign key in the UI.
To show the difference, we also setup the lookup data using the REGIONS table data.

Implementation:

We start with setting up the workspace. We use the normal ‘Fusion Web Application’ template. The template creates two projects, one model and one view controller project. once the names for the projects are entered, we start with the model project. We select the model project and select ‘Create Business Components from Table’. After copying the HR Connection to the project, we select the Countries and the Regions as entities

Entity Objects: Countries and Regions

Entity Objects: Countries and Regions

Next we select the two ViewObjects based on the EntityObjects build in the previous step

Updatable ViewObjects

Updatable ViewObjects

as we don’t need read only ViewObjects for this blog we skip this step and finally set a name for the application module

Application Module

Application Module

Next we create a new ViewObject which we define as ‘Rows populated at design time (Static List)’ which we use as lookup table.

Create Static VO

Create Static VO

Define as Static List

Define as Static List

Define the attributes and their data types. In this case we use an id (Number) and a String type as region name.

Attribute Id

Attribute Id

Attribute RegionName

Attribute RegionName

Next after the attributes for the static view are defined we add the values. Here you can enter as many rows as you like. There also can be more then two attributes. The sample only needs hte two attributes.

Empty Static List

Empty Static List

Filled Static List

Filled Static List

For the sample we define a second view object based on the COUNTRIES table of the HR schema. We use the two identical VO to show how to setup the LOV for the RegionId once using the entity based VO RegionView and once to setup the LOV using the static VO created before.

Create second VO to demonstrate setup of LOV using Static VO

Create second VO to demonstrate setup of LOV using Static VO

VO is based on Countries EO

VO is based on Countries EO

Use all Attributes

Use all Attributes

After the attributes are defiend we setup the LOV for the RegionId. For this we select the RegionId attribute and open the ‘List of Vaule:’ for the RegionId

Define the List Data Source for the LOV

Define the List Data Source for the LOV

Clicking the green plus sign we get the dialog where we define the choice list for the RegionId

Select the Static View as List Source

Select the Static View as List Source

Select Static VO as List Source

Select Static VO as List Source

Select the List Id

Select the List Id

Now as we want to see the region name instead of the Id we switch to the ‘UI Hints’ tab and select the regionName attribute from the list source

Select the RegionName

Select the RegionName

Shuffle it to the 'selected' side

Shuffle it to the ‘selected’ side

The same action are done for the CountriesView, only here we select the RegionsView as list source. Finally we add the new views to the data model of the application module. All other views we delete as we do’t need them.

Final Application Module

Final Application Module

Now we can test run the application module:

Test CountriesView

Test CountriesView

Test Countries4StaticRegionView1

Test Countries4StaticRegionView1

As expected we once see the region name from the regions table and once we get the static data we added to our static VO.

The final step for this blog is to setup a page in hte UI. For this we create one page with an af:panelSplitter. on hte left side we drag the CountriesView1 from the data control and drop it as ‘ADF Table…’. On hte right we drag the Countries4StaticRegionView1 and drop it as ‘ADF Table…’ too. We set the table to select single and allow sorting. Finally we set the table to ‘Click to Edit’ mode so that only on row can be edited at once.

Running Application: CountriesView1

Running Application: CountriesView1

Running Application: Countries4StaticRegionView1

Running Application: Countries4StaticRegionView1

Download:
You can download the workspace of the sample from here: ADF EMG Samples: BlogStaticVOLov.zip. The sample uses the HR schema and was build using JDeveloper 11.1.1.6.0 but should run in 11.1.1.5.0 and 11.1.2.x too.

JDeveloper & ADF af:inputListOfValues: enable case insensitive search

This blog entry describes a use case which is based on a question in the OTN JDeveloper & ADF forum.

Use case
In a data entry form there is one attribute which gets its values from an input list of values (af:inputListOfValues). The af:inputListOfValues component offers an input text field and a search facility which allows the use to look up the correct data. However, the look up uses a case sensitive search by default. The question is how to use a case insensitive search for the af:inputListOfValues to make the usability better for the user?

Implementation
The implementation of this use case can be done declarative, there is no java code needed. The sample, which you can download using the link provided at the end of the post, uses the Oracle HR schema to show how to do this. It build using JDeveloper 11.1.1.5.0 but should work in other versions too. We use the employees and jobs table from the HR schema. In the UI we use an input form for the employees and get the JobId via an af:inputListOfValues where the use can search for the right JobId.
The sample uses the default ‘Fusion Web Application’ application template as basis. The model project uses the two tables (employees and jobs) as business model. In the UI the search part of the af:inputListOfValues uses the ‘All Queriable Attributes’ for the search popup which is the automatically created view criteria for a view object. It shows all attributes of a view object which have the queriable property set to true. You find this property in the attribute section of the view object.
If you setup the LOV attribute in the emplyoees view object the default way, you end up with an inputListOfValues in the UI like:

inputListOfValue: Search popup using all queriable attributes

inputListOfValue: Search popup using all queriable attributes

Note that you have to use ‘A’ to find something. Using ‘a’ will not find anything. This is the problem we solve in this blog.

To implement an case insensitive search we have to create another view criteria in the Jobs view object. There we declare that we want to ‘Ignore Case’ for the attributes we are searching for. The final result of the view criteria looks like

JobsView: Create View Criteria

JobsView: Create View Criteria

Once this is saved we can open the EmployeesView and setup the model drivel LOV for the JobId of an employee row. Open the EmployeesView view object , select the Attributes node, select the JobId attribute and open the ‘List of Values’ for it. There we add a new entry resulting in the image below:

EmployeesView: setup LOV for JobId

EmployeesView: setup LOV for JobId

The essential part is to switch to the ‘UI Hints’ tab and there change the view criteria to use from ‘All Queriable Attributes’ to the view criteria created in the previous step.

EmployeesView: use own view criteria

EmployeesView: use own view criteria

Now after all is saved and compiled, lets run the application and see that the search popup for the af:inputListOfValues now uses our view criteria and indeed the search is case insensitive.

Search popup using case insensitive search

Search popup using case insensitive search

You can download the sample using this link: BlogCaseInsensitiveInputLOV.zip
The sample is build using JDev 11.1.1.5.0 and uses the HR schema.
The sample contains two pages Empdefault and Emp. Empdefault uses the normal LOV view criteria. The Emp page uses the view criteria created with case insensitive search.