Showing posts with label ADF 10g. Show all posts
Showing posts with label ADF 10g. Show all posts

Thursday, April 29, 2010

Client side Error Handling with validateRegExp on Decimal fields

There are undoubtedly more than one ways of handling the errors gracefully for your ADF inputText component. One of which is at the Model Layer using Validation at the Entity Objects the details of which can be seen here.
However, in some of the cases where we have an editable table dropped on the page and we need to provide the validation on all its fields, some of which are decimals, the various ways would be to use the various validators and converters as described here. However, this post describes 2 ways to handle the errors on the Decimal fields.

Note : To demonstrate the use of Decimal fields I've created a column Weight in the Employees table. Further I've created an Employees Entity Object, View Object and Application Module.


I also created a jspx page to Create/Update an Employee



Using the Validate Double Range :
Drag the validateDoubleRange validator from the Component Pallette under the JSF Core Menu and rop it under the inputText component. Remove ConvertNumber if any present. Just specify the range here as shown below.


At run time whenever an error occurs it shows the result in the following format.


However, the limitations of using this approach are :

  • You can not customize the message.
  • The Error messages are displayed after Submitting the page which involves a server call.

 Many times customers want client side validation messages in JavaScript alert boxes. The second approach demonstrates the same.

Using validateRegExp :
Validate Regular expression is a very efficient means to check for any format of the STRINGS. But unfortunately it can not be used for Numerical or Decimal data types. Even if you try to drop a validateRegExp validator under inputText, it works properly in case of errors but in case of correct value it throws an exception.



500 Internal Server Error
java.lang.IllegalArgumentException: 'value' is not of type java.lang.String. at oracle.adf.view.faces.validator.ValidatorUtils.assertIsString(ValidatorUtils.java:36) at oracle.adf.view.faces.validator.RegExpValidator.validate(RegExpValidator.java:103) at oracle.adf.view.faces.component.UIXEditableValue.validateValue(UIXEditableValue.java:378) at oracle.adf.view.faces.component.UIXEditableValue.validate(UIXEditableValue.java:206) at oracle.adf.view.faces.component.UIXEditableValue._executeValidate(UIXEditableValue.java:522) at oracle.adf.view.faces.component.UIXEditableValue.processValidators(UIXEditableValue.java:302) at oracle.adf.view.faces.component.ChildLoop$Validate.process(ChildLoop.java:67) at oracle.adf.view.faces.component.ChildLoop.runAlways(ChildLoop.java:39) at oracle.adf.view.faces.component.ChildLoop.runAlways(ChildLoop.java:30) at oracle.adf.view.faces.component.UIXColumn.processValidators(UIXColumn.java:70) at oracle.adf.view.faces.component.UIXCollection.processComponent(UIXCollection.java:822) at oracle.adf.view.faces.component.TableUtils$3.process(TableUtils.java:256) at ...

To remove this error, just change the data type of your attribute to String in the Entity Object as shown under. Please note the same Entity Object can be used for other View Objects also. Hence make sure that all the View Objects are in tact.


So everything is set. Just run the page now and see the output.


Sunday, January 31, 2010

Setting the current row of a view object with custom key programmatically

I came across a use-case where I needed to set the key of a View Object manually through the backing bean. Usually setCurrentRowWithKey() or setCurrentRowWithKeyValue() can be used to set the current row of a view object. But What if you don't know the exact key but part of it and you want to create the key yourself and set the current Row programmtically.  Well you can use the following function on click of a command button or customize it happily to put to any specific use...

    public String setNewRowKey() {
        // Get the iterator displayed on the Page
         FacesContext ctx = FacesContext.getCurrentInstance();
         Application app = ctx.getApplication();
         ValueBinding bind = app.createValueBinding("#{bindings}");
         DCIteratorBinding iter = ((DCBindingContainer) bind.getValue(ctx)).findIteratorBinding("DepartmentsEmployeeVOIterator");
         if (iter == null) {
           throw new RuntimeException("Iterator not found");
         }
         
         // Create the key manually. It requires providing all primary keys for all 
         // the Entity Objects included in the View Object
         Object [] keyValues = new Object[2];
         keyValues[0] = null;  // Any Department
         keyValues[1] = "114"; // Employee ID
         
         // find all the rows matching the above criteria using the RowSetIterator. 
         // You can also use the same to find rows matching any key criteria.
         Row [] rows = iter.getRowSetIterator().findByKey(new Key(keyValues), -1);
        
         if (rows.length > 0)  {
             // get the first row and its key and set current row of iterator with this key string
             iter.setCurrentRowWithKey(rows[0].getKey().toStringFormat(true));
         }
         
        return "navigation-rule";
    }




Saturday, January 9, 2010

Clear values in Search form fields

I have designed a Search form to search for specific records based on search criteria. But once I have searched I want to clear the criteria fields to conduct a fresh search. There are 3 ways





1. Reset the bind parameters of the view objects by calling them in the bean that can be found at the below links.
http://forums.oracle.com/forums/thread.jspa?messageID=2563498#2563498 


http://forums.oracle.com/forums/thread.jspa?messageID=1579998#1579998 


http://radio.weblogs.com/0118231/2006/11/21.html


2. Use ResetButton to reset the form parameters. But it will reset the form fields’ values to the previous search criteria parameters.


3. The third way originates from the user experience. According to my experience users are least concerned about the VO bind parameters being refreshed or not, but what they actually want is to clear the form instantly and preferably with no server call that means on the client-side itself. The reason for the same is that all countries/clients/users do not have very fast internet as to virtually diminish the time taken to reset the form. Hence this method came up to clear the search form using Java Script. This way might not be suitable for all the situations and also does not replace the other two mentioned above but still it is very much efficient and helpful to provide the end-users pleasant experience.
All you have to do is follow the below 3 steps and it is done.
  • Change your search form to <af:form> instead of <h:form>. After this the form looks like this.
<af:form id="searchForm">
   <af:panelPage title="Clear Search Form Parameters Example">
   <af:panelForm>





   <af:inputText id="firstName" value="#{bindings.TheFirstName.inputValue}"    label="#{bindings.TheFirstName.label}" required="#{bindings.TheFirstName.mandatory}"  columns="#{bindings.TheFirstName.displayWidth}">
      <af:validator binding="#{bindings.TheFirstName.validator}"/>
   </af:inputText>
   <af:inputText id="salary" value="#{bindings.TheSalary.inputValue}"  label="#{bindings.TheSalary.label}" required="#{bindings.TheSalary.mandatory}" columns="#{bindings.TheSalary.displayWidth}">
   <af:validator binding="#{bindings.TheSalary.validator}"/>
  </af:inputText>
  • Create a Clear CommandButton as shown below and set the onClick property as clearAllFormFields() function.
<af:panelButtonBar>
   <af:commandButton actionListener="#{bindings.ExecuteWithParams.execute}" text="Search"  disabled="#{!bindings.ExecuteWithParams.enabled}"/>
   <af:commandButton text="Clear" onclick="return clearAllFormFields();"/>
</af:panelButtonBar>


  • Now add the scriptlet function in the jspx page as shown below.
<script type="text/javascript">
   function clearAllFormFields(){
      //check if the object is not null. The object will be null when it is not rendered on the page  or is disabled. 
      if(document.forms["searchForm"].elements["firstName"] != undefined)


     document.forms["searchForm"].elements["firstName"].value="";
     if(document.forms["searchForm"].elements["salary"] != undefined)
     document.forms["searchForm"].elements["salary"].value="";
     return false;
   }
</script>

And it is done. Now just test run the page.


Monday, December 7, 2009

af:selectOneChoice : get the combo box value for static and dynamic list

I have seen very common requirement to process the value selected in the Single Selection Combo Box at run time. Following example tells how to get this value at runtime in the backing bean for static list and dynamic list.

1. Static List
Static list allows to add a fixed list of user defined values. The following image shows the static list created on the Department Id.



Following steps show how to get the value from this list at runtime.
  • Define the valueChangeListener Property of the DepartmentId field to some method of a bean. e.g. SelectOneChoiceValueGetter:getSelectOneChoiceValue(ValueChangeEvent valueChangeEvent)
  • Now go to the above value change listener method and add the following code

public void getSelectOneChoiceValue(ValueChangeEvent valueChangeEvent) {
        // take the selectOneChoice object from the valueChangeEvenet
        CoreSelectOneChoice selectOneChoice = (CoreSelectOneChoice)valueChangeEvent.getSource();
        
        //get the LOV items list object
        List selectOnechoiceItemList = selectOneChoice.getChildren();

        //traverse the list and get all the children items
        for (int i = 0; i < selectOnechoiceItemList.size(); i++) {
            if (selectOnechoiceItemList.get(i) instanceof CoreSelectItem) {
                //get list item
                CoreSelectItem csi = (CoreSelectItem)selectOnechoiceItemList.get(i);
                
                // get the new value selected and type cast it into actual class
                oracle.jbo.domain.Number num = (Number)valueChangeEvent.getNewValue();

                //check if the list value is similar to the new selected value
                if ((((String)csi.getValue()).equals(num.toString()))) {
                    System.out.println("Item Label :" + csi.getLabel());
                    System.out.println("Item Value :" + csi.getValue());
                    // here is your value. store it or print it
                }
            }
        }
    }

2. Dynamic List
Dynamic list is created when  the number of values to be shown in the list box are not fixed. e.g. a new department can be added in an organisation in future and hence the newly added department is expected to appear in the list box at run time. In this case we create a dynamic list where the vales of the list box come at runtime from some master source. Following image shows the dynamic list created for the Department Id.





In the page definition file following code gets added.

<list id="EmployeesView1DepartmentId" IterBinding="EmployeesView1Iterator" StaticList="false" ListOperMode="0" ListIter="DepartmentsViewIterator">
<AttrNames><Item Value="DepartmentId"/></AttrNames>
<ListAttrNames>
<Item Value="DepartmentId"/>
</ListAttrNames>
<ListDisplayAttrNames>
<Item Value="DepartmentName"/>
</ListDisplayAttrNames>
</list>


Following steps show how to get the value of a dynamic list at run time.
  • As defined earlier for static list, define the valueChangeListener Property of the DepartmentId field to some method of a bean. e.g. DynamicListValueGetter:getDynamicListValue(ValueChangeEvent valueChangeEvent)
  • Now go to the above value change listener method and add the following code
Note : You should have the bindings set as the managed Property in the Managed Bean.


public void getDynamicListValue(ValueChangeEvent valueChangeEvent) {
// get the bindings to the current page components 
BindingContainer bindings = getBindings(); 
 
try {
//get the control binding to the id of the List as written in the Page Definition file
JUCtrlListBinding listBinding = (JUCtrlListBinding)bindings.get("EmployeesView1DepartmentId");


// as this is a value change listener method, so the list binding contains the OLD value of the combo box and not the NEW one. 
//The new value is available there in the valueChangeEvent as the index. So point the list binding to current selected index first
listBinding.setSelectedIndex(Integer.parseInt(valueChangeEvent.getNewValue().toString()));


// Now receive the selected row of the list binding
Row selectedValue = (Row) listBinding.getSelectedValue();


//from this row you can get the desired attributes
System.out.println( "Item Label :" + selectedValue.getAttribute("DepartmentName"));
System.out.println("Item Value :" + selectedValue.getAttribute("DepartmentId"));

catch (Exception ex)  
{ex.printStackTrace();}
}

When you run the page and select an item from the combo box, the label and value of selected item are displayed in the Jdeveloper Console. Once you have got the values you can do whatever you want.