Please disable your adblock and script blockers to view this page

Search this blog

Showing posts with label af:query. Show all posts
Showing posts with label af:query. Show all posts

Thursday, 10 November 2016

Styling Input components inside af:query using ADF Skin


This another post is about af:query skinning, previously I have posted about changing the style of af:query buttons

ADF Skinning : Change color and style of af:query buttons in ADF Faces (Jdev 12.1.3)

Now this post is about styling input components inside af:query, Sometimes we need to change color, width, fonts of inputText, selectOneChoice that are inside af:query and that time simple skin selector doesn't do the job

Monday, 4 May 2015

ADF Skinning : Change color and style of af:query buttons in ADF Faces (Jdev 12.1.3)

Hello All,

This is another post about ADF Skinning , in this post i am going to show you that how can we change button's style in af:query component
Actually this is very easy , if we define some styles for af:button component in our css file then it will be applicable on af:query's buttons (Search, Reset, Advanced, Save etc) too

Suppose i have defined this in css file

af|button{
    color:navy;
    font-weight:bold;
}
 

Now it will change color of all buttons of application including af:query
See this snap after applying this skin




But if you have a requirement to use different style in af:query buttons or you don't want to change color of all buttons
Then it is not that much easy as it seems

There is a selector to style buttons of af:query - af|query::button 
But this works only if buttons are af:commandButton not af:button
See from docs-

af|query::button Styles the buttons of the query component. Note that this skin selector is only present when the skin selector -tr-button-type is set to 'old', and the query buttons are rendered as af:commandButtons. When the -tr-button-type is set to 'unified', the query buttons are rendered as af:buttons and have the default stylings for af:button applied, so that query buttons have the same look and feel as all other buttons. Tip: If you skin this selector's background-image, you may also want to skin it for :hover, :active, :focus. The :disabled state is currently not supported. Please note that for buttons :active and :focus pseudo-classes do not work in IE7. IE7 also does not allow disabled buttons to be styled. It is recommended that you use the .AFButton*:alias selectors as a shortcut to skin all button components the same.

So for this first i have to change -tr-button-type selector to old so that i can use af|query::button
Now see the css


af|query {
    -tr-button-type: old;
}
 af|query::button {
    color: red;
    font-weight:bold;
}

 af|query::button:hover {
    color: Orange;
    font-weight:bold;
}

 af|query::button:focus {
    color: maroon;
    font-weight:bold;
}

af|button{
    color:navy;
    font-weight:bold;
}

Check the output-

To use specific style for af:query you can create styleClass in css file and put this in styleClass property of af:query
Suppose i have two af:query components on page and i want to use different style for both
For this i have define two different styleClass in css file like this-


af|query {
    -tr-button-type: old;
}
 .mystyle1 af|query::button {
    color: red;
    font-weight:bold;
}

.mystyle2 af|query::button {
    color: darkgreen;
    font-weight:bold;
}

and on page put myStyle1 in styleClass property of first af:query component and myStyle2 in second af:query
See how it looks now -


Cheers, Happy Learning  ☺

Thursday, 15 May 2014

Overriding Reset button action (QueryOperationListener) of af:query, Changing query mode, Handling QueryOperationEvent programmatically-Oracle ADF

Hello All ,
previously i had a requirement of validating af:query fields so i have found two ways to do that
see -Overriding default query listener ,field validation of af:query- Oracle ADF

now i have to set some values in af:query when user clicks on Reset button of query so to do that i have to override default QueryOperationListener in order to handle QueryOperationEvent  



Oracle docs says-

af:query- The query component provides the user the ability to perform a query based on a saved search or personalize saved searches in Oracle ADF. The component displays a search panel with various elements, each of which help the user to accomplish various tasks. 

QueryOperationListener- QueryOperationListener class. A registered queryOperationListener is invoked when the user's action results a queue and broadcast of QueryOpertionEvent on the component. For example, click the delete icon in the QuickCriteria component or click "Save", "Reset" etc buttons in Query component to perform a Query Operation.

 QueryOperationEvent-A user can perform various operations on saved searches while interacting with a query component. These actions include creating, overriding, deleting, duplicating, selecting, resetting and updating a saved search

want to read more-  
http://docs.oracle.com/cd/E17904_01/apirefs.1111/e10684/oracle/adf/view/rich/event/QueryOperationListener.html
http://jdevadf.oracle.com/adf-richclient-demo/docs/apidocs/oracle/adf/view/rich/event/QueryOperationEvent.html  

so i have created a QueryOperationListener in managed bean that communicates with QueryOperationEvent

in this method we can capture various events of af:query as reset,update
so for this use-case i have to capture reset and set desired values in query attribute (viewObject's bind variable) , here i am using Departments table of HR Schema



now see the code (i have to set Human Resource department on reset in search panel) - how to capture raised event when user clicks on Reset button of af:query


    /**Custom QueryOperationListener that hadles variois events raised by af:query
     * @param queryOperationEvent
     */
    public void deptSeacrhQueryOperationList(QueryOperationEvent queryOperationEvent) {
        //Invoke default operation listener
        invokeEL("#{bindings.DepartmentsVOCriteriaQuery.processQueryOperation}", Object.class,
                 QueryOperationEvent.class, queryOperationEvent);

        System.out.println("Query Event is-" + queryOperationEvent.getOperation().name());
        //Check that current operation is RESET
        if (queryOperationEvent.getOperation().name().equalsIgnoreCase("RESET")) {
            DCIteratorBinding iter = (DCIteratorBinding) getBindings().get("Departments1Iterator");

            ViewObjectImpl vo = (ViewObjectImpl) iter.getViewObject();
            // Setting the value of bind variable
            vo.ensureVariableManager().setVariableValue("BindDeptNm", "Human Resource");
        }
    }

to invoke Expression use this method


    /**
     * @param expr
     * @param returnType
     * @param argTypes
     * @param args
     * @return
     */
    public Object invokeMethodExpression(String expr, Class returnType, Class[] argTypes, Object[] args) {
        FacesContext fc = FacesContext.getCurrentInstance();
        ELContext elctx = fc.getELContext();
        ExpressionFactory elFactory = fc.getApplication().getExpressionFactory();
        MethodExpression methodExpr = elFactory.createMethodExpression(elctx, expr, returnType, argTypes);
        return methodExpr.invoke(elctx, args);
    }

    /**
     * @param expr
     * @param returnType
     * @param argType
     * @param argument
     * @return
     */
    public Object invokeEL(String expr, Class returnType, Class argType, Object argument) {
        return invokeMethodExpression(expr, returnType, new Class[] { argType }, new Object[] { argument });
    }

now run this page and check on click of reset button this listener is invoked and sets the value of af:query field
Default page view -on-load


 after click on Reset-


other than this reset we can handle other events of af:query (for saved search there are various events based on corresponding operations) as DELETE, UPDATE, CREATE


on clicking various button of this personalized search box we get respective operation  name in managed bean and can handle as  done for RESET operation

Changing mode of default search panel (af:query) of ADF-
this is nothing but  2 lines that changes the mode of af:query - Basic to Advanced & Advanced to Basic

so dropped a button on page to change af:query search mode and see the code of ActionListener for this


//Binding of af:query in managed bean  
  private RichQuery queryPanelDept;
    
    public void setQueryPanelDept(RichQuery queryPanelDept) {
        this.queryPanelDept = queryPanelDept;
    }
    public RichQuery getQueryPanelDept() {
        return queryPanelDept;
    }


    private String current_mode = "B";

    /**Method Action to change mode of af:query
     * @param actionEvent
     */
    public void changeModeAction(ActionEvent actionEvent) {
        if (current_mode == "B") {
            getQueryPanelDept().getValue().changeMode(QueryDescriptor.QueryMode.ADVANCED);
            current_mode = "A";
        } else if (current_mode == "A") {
            getQueryPanelDept().getValue().changeMode(QueryDescriptor.QueryMode.BASIC);
            current_mode = "B";
        }
    }

now run page and see-



Cheers - Happy learning :-) Download Sample ADF App

Friday, 27 December 2013

Overriding default query listener ,field validation of af:query- Oracle ADF


Hello All,
this post talks about a common requirement - can we apply custom validation in af:query fields ? yes , we can do that by overriding default query listener of af:query component

What af:query is ?

see- Oracle Docs-af:query
"The query component provides the user the ability to perform a query based on a saved search or personalize saved searches. The component displays a search panel with various elements, each of which help the user to accomplish various tasks."


Follow steps to apply validation on af:query-
  • Here i am taking example of Departments table of HR Schema
  • First create business components for Departments table


  • then create  bind variables and a view-criteria in departments view object



  • See the view criteria is applied for LocationId, ManagerId and Department Name
  • Now create a page and drop criteria with table on page- it will look like this

  • Next is to select af:query on page and go to property inspector and copy text of default query listener



  • Now create a managed bean and create a custom query listener for af:query

     
  • In this custom query listener , in this example i am checking for negative Location Id and Manager Id, if there is any negative values ,custom method will show a message otherwise default queryListener will be executed
  • We can get af:query's components value using 2 methods
    First One  - Using Bind Variable (getNamedWhereClauseParam)
    Second One - Using QueryDescriptor and ConjunctionCriterion
  • I'm going to explain both methods - see code of custom query listener using first method, two generic methods will be used in this process to invoke expression language and to get BindingContainer of current context

  •     /**Method to invoke EL Expression
         * @param el
         * @param paramTypes
         * @param params
         * @return
         */
        public static Object invokeEL(String el, Class[] paramTypes, Object[] params) {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            ELContext elContext = facesContext.getELContext();
            ExpressionFactory expressionFactory = facesContext.getApplication().getExpressionFactory();
            MethodExpression exp = expressionFactory.createMethodExpression(elContext, el, Object.class, paramTypes);
    
            return exp.invoke(elContext, params);
        }
    
        /**Method to get Binding Container of current page
         * @return
         */
        public BindingContainer getBindings() {
            return BindingContext.getCurrent().getCurrentBindingsEntry();
        }
    

  • See the first method to get af:query components value and validate that

  •     /**Custome Query Listener- Using getNamedWhereClauseParam
         * @param queryEvent
         */
        public void customQueryListener(QueryEvent queryEvent) {
            String deptName = null;
            Integer locId = null;
            Integer mgrId = null;
    
            /**Get Iterator of Table*/
            DCIteratorBinding iter = (DCIteratorBinding)getBindings().get("DepartmentsView1Iterator");
    
            /**Get ViewObject from Iterator*/
            ViewObjectImpl vo = (ViewObjectImpl)iter.getViewObject();
    
            /**Get Bind Variable's Value*/
            if (vo.getNamedWhereClauseParam("LocIdBind") != null) {
                locId = Integer.parseInt(vo.getNamedWhereClauseParam("LocIdBind").toString());
            }
            if (vo.getNamedWhereClauseParam("MgrIdBind") != null) {
                mgrId = Integer.parseInt(vo.getNamedWhereClauseParam("MgrIdBind").toString());
            }
            if (vo.getNamedWhereClauseParam("DeptNmBind") != null) {
                deptName = vo.getNamedWhereClauseParam("DeptNmBind").toString();
            }
    
            /**Check for Negative values*/
            if ((locId != null && locId < 0) || (mgrId != null && mgrId < 0)) {
                FacesMessage msg = new FacesMessage("Id Value can not be negative");
                msg.setSeverity(FacesMessage.SEVERITY_ERROR);
                FacesContext.getCurrentInstance().addMessage(null, msg);
            } else {
                /**Execute default query listener with help of invokeEL method*/
    
                invokeEL("#{bindings.DepartmentsViewCriteriaQuery.processQuery}", new Class[] { QueryEvent.class },
                         new Object[] { queryEvent });
            }
        }
    

  • And Second Method using QueryDescriptor is-

  •     /**Custom Query Listener-Using QueryDescriptor
         * @param queryEvent
         */
        public void customqueryProcess(QueryEvent queryEvent) {
            String deptName = null;
            Integer locId = null;
            Integer mgrId = null;
    
            /**Reference-Frank Nimphius Example- ADF Code Corner
           * http://www.oracle.com/technetwork/developer-tools/adf/learnmore/85-querycomponent-fieldvalidation-427197.pdf
           * */
            QueryDescriptor qd = queryEvent.getDescriptor();
    
            ConjunctionCriterion conCrit = qd.getConjunctionCriterion();
            //access the list of search fields
            List<Criterion> criterionList = conCrit.getCriterionList();
            //iterate over the attributes to find FromDate and ToDate
            for (Criterion criterion : criterionList) {
                AttributeDescriptor attrDescriptor = ((AttributeCriterion)criterion).getAttribute();
    
                if (attrDescriptor.getName().equalsIgnoreCase("DepartmentName")) {
                    deptName = (String)((AttributeCriterion)criterion).getValues().get(0);
    
                } else {
                    if (attrDescriptor.getName().equalsIgnoreCase("LocationId")) {
                        locId = (Integer)((AttributeCriterion)criterion).getValues().get(0);
    
                    }
                }
                if (attrDescriptor.getName().equalsIgnoreCase("ManagerId")) {
                    mgrId = (Integer)((AttributeCriterion)criterion).getValues().get(0);
    
                }
            }
            if ((locId != null && locId < 0) || (mgrId != null && mgrId < 0)) {
                FacesMessage msg = new FacesMessage("Id Value can not be negative");
                msg.setSeverity(FacesMessage.SEVERITY_ERROR);
                FacesContext.getCurrentInstance().addMessage(null, msg);
            } else {
                /**Process default query listener*/
                invokeEL("#{bindings.DepartmentsViewCriteriaQuery.processQuery}", new Class[] { QueryEvent.class },
                         new Object[] { queryEvent });
            }
    
        }
    

  • Now Run your application and check it for negative values

Cheers- Download Sample App Happy Learning :-)


Wednesday, 24 July 2013

Implementing custom search form in ADF programmatically (Without using af:query)

Sometimes we need to implement custom search instead of using adf query component.
To implement custom search form , i have used a quite beautiful way to handle search and reset functionality for a View Object.
In this post i am taking Employees Table (Default HR Schema) to search and reset af:table.

  • First create a Fusion Web Application and create model (EO,VO and AM) using Employees table
  • Now suppose we have to search on 4 fields (EmployeeId, FirstName, Email, Salary) , so for this i have created a new read only ViewObject from dual
  •  This VO from dual is created to be used as Search form on page
  •  Now to make search effective on Employees VO , i have created 4 bind variable for corresponding fields in Employees ViewObject



  •  Now i have created a ViewCriteria using these 4 bind variables to re-query ViewObject  data
  •  This ViewCriteria will be executed each time when value of bind variable is changed, now this is the time to set value of bind variables, so i have dragged dual vo as a form on page, and added 2 button for Search and Reset
  •  To View Search Result , Employees Table is there on page
  •  Now to get value from Form Field to bean , i have created binding for all 4 fields in bean
  •  Now i have created ActionListener for Search button- in this code i have get value from page using component bindings and passed in Employees ViewObject's bind variable in order to execute viewCriteria.

  •     public void searchButton(ActionEvent actionEvent) {
            searchAMImpl am = (searchAMImpl)resolvElDC("searchAMDataControl");
            ViewObject empVo = am.getEmployees1();
            empVo.setNamedWhereClauseParam("EmpIdBind", empIdPgBind.getValue());
            empVo.setNamedWhereClauseParam("FirstNmBind", firstNmPgBind.getValue());
            empVo.setNamedWhereClauseParam("EmailBind", emailPgBind.getValue());
            empVo.setNamedWhereClauseParam("SalaryBind", salaryPgBind.getValue());
            empVo.executeQuery();
        }
    

  • Once value is set in bind variable , view criteria is executed and Search result will be shown in resultant table- Run your application and see
  • To reset values in table and search form, see the managed bean code of Reset button

  •     public void resetButton(ActionEvent actionEvent) {
            searchAMImpl am = (searchAMImpl)resolvElDC("searchAMDataControl");
            ViewObject empVo = am.getEmployees1();
            ViewObject attrVo=am.getattr1();
            empVo.setNamedWhereClauseParam("EmpIdBind", null);
            empVo.setNamedWhereClauseParam("FirstNmBind", null);
            empVo.setNamedWhereClauseParam("EmailBind", null);
            empVo.setNamedWhereClauseParam("SalaryBind", null);
            empVo.executeQuery();
            attrVo.executeQuery();
          
        }
    

  • Click on reset button and page value are set to default

  • This is how we can implement custom search using ADF components, you can apply validations, auto suggest feature etc while using this custom search
          Cheers :-)  Download Sample App