Topics covered
1.
Passing user entered values in search panel to a DB package before executing a search.
2.
How to get 2 date values entered using between operator in advanced mode for further processing.
3.
How to hide Advanced button from af:query search panel?
4.
How to hide Match All and Any radio option in af:query panel?
5.
How to restrict operators for search fields in advanced mode in af:query panel if field is part of view criteria?
6.
How to restrict operators for search fields in advanced mode in af:query panel if field is not part of view criteria?
7.
How to hide “Add Fields” button in af:query search panel?
8. Code snippet to handle "on-before" and "on-after" as well handling null values in default between operator
ADF Search Query Panel (af:query)
The af:query component displays a search panel with various elements and it executes a query based on search criteria . In this document, I will explain possible customizations and some handy tips.
To achieve basic functionality of search panel, all we have to do is to drag and drop “All Queriable Attributes” (Named Criteria) from Data control panel. If we want specific criteria then we create view criteria on the particular view and will drag and drop on to a page as a query panel.
Now I will explain different use cases where you have to do customization and achieve the functionality.
1: Suppose, I want to pass user entered values in search panel to a DB package before executing a search. Or to put it in other way, I need to hold the values for some business logic before executing search.
Solution: Customize the queryListener of your af:query panel.
When you drag and drop view criteria to a page as a query panel, by default query listener of your af:query is
queryListener="#{bindings.<vo>CriteriaQuery.processQuery}" .
Change this and execute processQuery operation from your bean method
Ex:
#{backingBeanScope.Test BackingBean.customQueryListener}
Now logic for your cutomQueryListener method is as follows
public void cutomQueryListener(QueryEvent queryEvent){
String EmployeeId = null;
// Query Event is delivered when a query action is triggered
QueryDescriptor qd = queryEvent.getDescriptor();
// This line will represent group of criterion objects
ConjunctionCriterion conCrit = qd.getConjunctionCriterion();
//access the list of all search fields
List<Criterion> criterionList = conCrit.getCriterionList();
for (Criterion criterion : criterionList) {
AttributeDescriptor attrDescriptor = ((AttributeCriterion)criterion).getAttribute();
if (attrDescriptor.getName().equalsIgnoreCase("EmployeeId")) { // EmployeeId is one of the query items in the search panel
EmployeeId = (String)((AttributeCriterion)criterion).getValues().get(0);
//This is how we will access the query field
System.out.println("EmployeeId :" + EmployeeId );
}
Note: At this moment, I have value entered in EmployeeId field. So, I can do whatever validation on the user entered value or pass it to package call before executing search query.
//Execute the query Listener using EL. This will execute the query component .If u see the exp , this was initially applied to QueryListener.. Later we assigned QueryListener to our custom method.
invokeMethodExpression("#{bindings.VOCriteriaQuery.processQuery}", queryEvent);
}
//helper method to execute the QueryListener EL
private void invokeMethodExpression(String expr, QueryEvent queryEvent) {
FacesContext fctx = FacesContext.getCurrentInstance();
ELContext elContext = fctx.getELContext();
ExpressionFactory eFactory =
fctx.getApplication().getExpressionFactory();
MethodExpression mexpr =
eFactory.createMethodExpression(elContext, expr, Object.class,
new Class[] { QueryEvent.class });
mexpr.invoke(elContext, new Object[] { queryEvent });
}
2: How to get 2 date values entered using between operators in advanced mode for further processing.
Say for Example, we have “Active Date” field in search panel and we want to get “FromActiveDate” and “ToActiveDate” from this search field. In this case, we need to find whether search panel is in advanced mode or basic mode.
You can achieve this by using below line of code
qdesc.getUIHints().get(QueryDescriptor.UIHINT_MODE).equals(QueryDescriptor.QueryMode.ADVANCED)
Complete code logic is as shown below
if (attrDescriptor.getName().equalsIgnoreCase("ActiveDate")) {
// Checking whether it is advanced mode
if (qdesc.getUIHints().get(QueryDescriptor.UIHINT_MODE).equals(QueryDescriptor.QueryMode.ADVANCED)) {
Map<AttributeCriterion, Operator> changedAttrs = new HashMap<AttributeCriterion, Operator>();
AttributeCriterion ac = (AttributeCriterion) criterion;
Operator operator = ac.getOperator();
if ("BETWEEN".equalsIgnoreCase(operator.getValue().toString())) {
oracle.jbo.domain.Date effFromDate1 =
(oracle.jbo.domain.Date) ((AttributeCriterion) criterion).getValues().get(0);
if (null != effFromDate1) {
effectiveFromDate = effFromDate1.getValue();
}
oracle.jbo.domain.Date effToDate1 =
(oracle.jbo.domain.Date) ((AttributeCriterion) criterion).getValues().get(1);
if (null != effToDate1) {
effectiveToDate = effToDate1.getValue();
}
} else {
oracle.jbo.domain.Date effFromDate1 =
(oracle.jbo.domain.Date) ((AttributeCriterion) criterion).getValues().get(0);
if (null != effFromDate1) {
effectiveFromDate = effFromDate1.getValue();
}
}
//Basic mode:
} else {
oracle.jbo.domain.Date effectiveFromDate1 =
(oracle.jbo.domain.Date) ((AttributeCriterion) criterion).getValues().get(0);
if (null != effectiveFromDate1) {
effectiveFromDate = effectiveFromDate1.getValue();
}
}
3. How to hide Advanced button from af:query
From the af:Query properties, set property values as modeChangeVisible="false"
Select af:query in the page, and from the properties window, under appearance section you can find the modeChangeVisible property as shown below screenshot
4. How to hide Match All and Any radio option in af:query panel
1. Edit View Criteria
2. In the Criteria UI hints – Un check the Show Match all and Match Any check box
Note: To make required and put ** for the af:query panel attributes make criteria item as required for * and selectively required for **
5. How to restrict operators for search fields in advanced mode in af:query panel
1. Edit view criteria
2. Under Criteria Definition tab, select criteria item
3. Go to “Custom Operators” tab in the bottom
4. Remove operators which you do not want to show for particular attributes in advanced mode
6.
What if field is not part of your view criteria and still you want to restrict the operators.
Approach to be followed
In the above case you still achieve like the way we used to do in 11g by using
<CompOper>
To make our life easier,
1) first add attribute to view criteria,
2)remove unnecessary operators form custom operators
3)Go to source mode, copy CompOper from view criteria item and put it some where for reference
4)remove the attribute from view criteria
5)Go to source mode, find the attribute then copy the CompOper properties which you copied in step3
Then go to source mode and then find out the attribute for which you want to restrict the operators then use <CompOper>
for Ex, In below example, I have restricted all the operators except equals for string attribute
<ViewAttribute
Name="Status"
IsPersistent="false"
PrecisionRule="true"
Precision="1"
Type="java.lang.String"
ColumnType="VARCHAR2"
AliasName="STATUS"
Expression="STATUS"
SQLType="VARCHAR"
LOVName="LOV_Status">
<DesignTime>
<Attr Name="_DisplaySize" Value="1"/>
</DesignTime>
<CompOper
Name="Status_Oper"
ToDo="-1"
Oper="<"
MinCardinality="1"
MaxCardinality="1"/>
<CompOper
Name="Status_Oper1"
ToDo="-1"
Oper="<="
MinCardinality="1"
MaxCardinality="1"/>
<CompOper
Name="Status_Oper2"
ToDo="-1"
Oper="<>"
MinCardinality="1"
MaxCardinality="1"/>
<CompOper
Name="Status_Oper3"
ToDo="-1"
Oper=">"
MinCardinality="1"
MaxCardinality="1"/>
<CompOper
Name="Status_Oper4"
ToDo="-1"
Oper=">="
MinCardinality="1"
MaxCardinality="1"/>
<CompOper
Name="Status_Oper5"
ToDo="-1"
Oper="BETWEEN"
MinCardinality="1"
MaxCardinality="1"/>
<CompOper
Name="Status_Oper6"
ToDo="-1"
Oper="CONTAINS"
MinCardinality="1"
MaxCardinality="1"/>
<CompOper
Name="Status_Oper7"
ToDo="-1"
Oper="DOESNOTCONTAIN"
MinCardinality="1"
MaxCardinality="1"/>
<CompOper
Name="Status_Oper8"
ToDo="-1"
Oper="ENDSWITH"
MinCardinality="1"
MaxCardinality="1"/>
<CompOper
Name="Status_Oper9"
ToDo="-1"
Oper="ISBLANK"
MinCardinality="1"
MaxCardinality="1"/>
<CompOper
Name="Status_Oper10"
ToDo="-1"
Oper="ISNOTBLANK"
MinCardinality="1"
MaxCardinality="1"/>
<CompOper
Name="Status_Oper11"
ToDo="-1"
Oper="NOTBETWEEN"
MinCardinality="1"
MaxCardinality="1"/>
<CompOper
Name="Status_Oper12"
ToDo="-1"
Oper="STARTSWITH"
MinCardinality="1"
MaxCardinality="1"/>
<Properties>
<SchemaBasedProperties>
<CONTROLTYPE
Value="choice"/>
</SchemaBasedProperties>
</Properties>
</ViewAttribute>
7. How to hide “Add Fields” button in af:query search panel?
In the, jsff(or in your page), within af:query component add a facet footer and specify width and height as 1 as shown below
<af:query id="qryId1" headerText="SEARCH"
disclosed="true"
value="#{bindings.TestVOCriteriaQuery.queryDescriptor}"
model="#{<model bidning value> }"
queryListener="#{<query listener value>}"
queryOperationListener="#{bindings. VOCriteriaQuery.processQueryOperation}"
maxColumns="2" rows="3" fieldWidth="30%" labelWidth="70%"
resultComponentId="::at1:_ATp:t1">
<f:facet name="footer">
<af:spacer width="1" height="1" id="s3"/>
</f:facet>
</af:query>
8. Code snippet to handle "on-before" and "on-after" as well handling null values in default between operator
if (attrDescriptor.getName().equalsIgnoreCase("ActiveDate")) {
Map<AttributeCriterion, Operator> changedAttrs = new HashMap<AttributeCriterion, Operator>();
AttributeCriterion ac = (AttributeCriterion) criterion;
Operator operator = ac.getOperator();
if ("BETWEEN".equalsIgnoreCase(operator.getValue().toString())) {
oracle.jbo.domain.Date effFromDate1 =
(oracle.jbo.domain.Date) ((AttributeCriterion) criterion).getValues().get(0);
if (null != effFromDate1) {
effectiveFromDate = effFromDate1.getValue();
}
oracle.jbo.domain.Date effToDate1 =
(oracle.jbo.domain.Date) ((AttributeCriterion) criterion).getValues().get(1);
if (null != effToDate1) {
effectiveToDate = effToDate1.getValue();
}
String op = null;
String opDate = null;
Object val = null;
List<Object> list = (List<Object>)ac.getValues();
if (list.get(0) == null && list.get(1) != null) {
op = "<=";
opDate = "ONORBEFORE";
val = "1900-01-01";
list.set(0, val);
} else if (list.get(1) == null && list.get(0) != null) {
op = ">=";
opDate = "ONORAFTER";
val = "9999-01-01";
list.set(1, val);
}
if (op != null) {
changedAttrs.put(ac, operator);
for (Operator o : ac.getAttribute().getSupportedOperators()) {
if (o.getValue().toString().equalsIgnoreCase(op) || o.getValue().toString().equalsIgnoreCase(opDate)) {
operator = o;
break;
}
}
ac.setOperator(operator);
}
} else {
oracle.jbo.domain.Date effFromDate1 =
(oracle.jbo.domain.Date) ((AttributeCriterion) criterion).getValues().get(0);
if (null != effFromDate1) {
effectiveFromDate = effFromDate1.getValue();
}
}
}
References:
1. ADF code corner: af:query component field validation by Frank Nimphius
2. http://www.jobinesh.com/2013/01/prart-2-hiding-unwanted-operators-in.html - By Jobinesh Purushothaman