This chapter describes how to use the query
and quickQuery
search panel components.
This chapter includes the following sections:
The query
and quickQuery
components are used to search through data sets. The query
component provides a comprehensive set of search criteria and controls, while the quick
Query
component can be used for searching on a single criterion.
The query
component supports the following functionality:
Selecting and searching against multiple search criteria
Dynamically adding and deleting criteria items
Selecting search operators (associated to a single criterion)
Choosing match all or match any conjunction
Displaying in a basic, advanced, compact, simple, or design mode
Creating saved searches
Personalizing saved searches
By default, the advanced mode of the query
component allows the user to add and delete criteria items to the currently displayed search. However you can implement your own QueryModel
class that can hide certain features in basic mode (and expose them only in advanced mode). For example, you might display operators only in advanced mode or display more criteria in advanced mode than in basic mode.
Typically, the results of the query are displayed in a table or tree table, which is identified using the resultComponentId
attribute of the query
component. However, you can display the results in any other output components as well. The component configured to display the results is automatically rerendered when a search is performed.
Figure 12-1 shows an advanced mode query
component with three search criteria.
You can create seeded searches, that is, searches whose criteria are already determined and from which the user can choose, or you can allow the user to add criterion and then save those searches. For example, Figure 12-1 shows a seeded search for an employee. The user can enter values for the criteria on which the search will execute. The user can also choose the operands (greater than, equals, less than) and the conjunction (matches all or matches any, which creates either an "and" or "or" query). The user can click the Add Fields dropdown list to add one or more criteria and then save that search. If the application is configured to use persistence, then those search criteria, along with the chosen operands and conjunctions, can be saved and reaccessed using a given search name (for more information about persistence, see Chapter 31, "Allowing User Customization on JSF Pages").
The quickQuery
component is a simplified version of the query
component. The user can perform a search on any one of the searchable attributes by selecting it from a dropdown list. Figure 12-2 shows a quickQuery
component in horizontal layout.
Both the query
and quickQuery
components use the QueryModel
class to define and execute searches. Create the associated QueryModel
classes for each specific search you want users to be able to execute.
Tip:
Instead of having to build your ownQueryModel
implementation, you can use ADF Business Components, which provide the needed functionality. For more information, see the "Creating ADF Databound Search Forms" chapter of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.The QueryModel
class manages QueryDescriptor
objects, which define a set of search criteria. The QueryModel
class is responsible for creating, deleting, and updating QueryDescriptor
objects. The QueryModel
class also retrieves saved searches, both those that are seeded and those that the user personalizes. For more information, refer to the ADF Faces Javadoc.
You must create a QueryDescriptor
class for each set of search criteria items. The QueryDescriptor
class is responsible for accessing the criteria and conjunction needed to build each seeded search. It is also responsible for dynamically adding, deleting, or adding and deleting criteria in response to end-user's actions. The QueryDescriptor
class also provides various UI hints such as mode, auto-execute, and so on. For more information, refer to the ADF Faces Javadoc. One QueryModel
class can manage multiple QueryDescriptor
objects.
When a user creates a new saved search, a new QueryDescriptor
object is created for that saved search. The user can perform various operations on the saved search, such as deleting, selecting, resetting, and updating. When a search is executed or changed, in addition to calling the appropriate QueryModel
method to return the correct QueryDescriptor
object, a QueryOperationEvent
event is broadcast during the Apply Request Values phase. This event is consumed by the QueryOperationListener
handlers during the Invoke Application phase of the JSF lifecycle. The QueryOperationEvent
event takes the QueryDescriptor
object as an argument and passes it to the listener. ADF Faces provides a default implementation of the listener. For details of what the listener does, see Table 12-2.
For example, updating a saved search would be accomplished by calling the QueryModel
's update()
method. A QueryOperationEvent
event is queued, and then consumed by the QueryOperationListener
handler, which performs processing to change the model information related to the update operation.
The query operation actions that generate a QueryOperationEvent
event are:
Saving a search
Deleting a saved search
Resetting a saved search
Selecting a different saved search
Updating a saved search
Updating the value of a criterion that has dependent criteria
The hasDependentCriterion
method of the AttributeCriterion
class can be called to check to see whether a criterion has dependents. By default, the method returns false
, but it returns true
if the criterion has dependent criteria. When that criterion's value has changed, a QueryOperationEvent
is queued for the Update Model Values JSF lifecycle phase. The model will need a listener to update the values of the dependent criterion based on the value entered in its root criteria.
Before you can use the query
components, you must to create your QueryModel
classes.
Tip:
You can use thequickQuery
component without implementing a QueryModel
class. However, you will have to add some additional logic to a managed bean. For more information, see Section 12.3.2, "How to Use a quickQuery Component Without a Model."Figure 12-3 shows the class diagram for a QueryModel
class.
Create implementations of each of the interface classes shown in Figure 12-3. Implement one QueryModel
class and then a QueryDescriptor
class with appropriate criteria (operators and values) for each system-seeded search. For example implementations of the different model classes for a query, see the classes located in the oracle.adfdemo.view.query.rich
package of the ADF Faces sample application.
Note:
If your query uses composition (for example,ConjunctionCriterion 1...n
with AttributeCriterion/ConjunctionCriterion
), this relationship is not enforced by the abstract interfaces. Your implementation must decide whether to use composition over association, and determine how the lifecyle of these objects are managed.Create a QueryListener
handler method on a managed bean that listens for the QueryEvent
event (this will be referenced by a button on the query
component). This listener will invoke the proper APIs in the QueryModel
to execute the query. Example 12-1 shows the listener method of a basic QueryListener
implementation that constructs a String
representation of the search criteria. This String
is then displayed as the search result.
Query component has a refresh()
method on the UIXQuery component. This method should be called when the model definition changes and the query component need to be refreshed (i.e., all its children removed and recreated). When a new criterion is added to the QueryDescriptor
or an existing one is removed, if the underlying model returns a different collection of criterion objects than what the component subtree expects, then this method should be called. QueryOperationListener
, QueryListener
, and ActionListener
should all call this method. The query component itself will be flushed at the end of the Invoke Application Phase. This method is a no-op when called during the Render Response Phase.
To better understand what your implementations must accomplish, Table 12-1 and Table 12-2 map the functionality found in the UI component shown in Figure 12-4 with the corresponding interface.
Table 12-1 shows UI artifacts rendered for the query
component, the associated class, class property, and methods used by the artifact.
Table 12-1 Query UI Artifacts and Associated Model Class Operations and Properties
UI Artifact | Class Property/Methods Used | Comments | |
---|---|---|---|
1 |
Search panel |
The |
Based on a saved search. |
2 |
Disclosure icon |
Opens or closes the search panel |
|
3 |
Match type radio button |
Available through the |
Displays the default conjunction to use between search fields, when a query is performed. If a default is set, and it is the same for all search fields, it appears selected. If the search fields are configured such that a mix of different conjunctions must be used between them, then a value may not be selected on the UI. For example, if the The Match Type will be read only if the |
4 |
Group of search fields |
The collection of search fields for a |
Displays one or more search fields associated with the currently selected search. |
5 |
Search field |
An An The The |
Each search field contains a label, an operator, one or more value components (for example, an input text component), and an optional delete icon. The information required to render these can be either specific to an instance of a search field (in a saved search) or it can be generic and unchanging regardless of which saved search it is part of. For example, assume an Employee business object contains the search fields Employee Name and Salary. A user can then configure two different searches: one named Low Salaried Employees and one named High Salaried Employees. Both searches contain two search fields based on the Regardless of the search selected by the user, the search field for Salary always has to render a number component, and the label always has to show Salary. |
6 |
Saved Searches dropdown |
System- and user-saved searches are available through the methods |
Displays a list of available system- and user-saved searches. A Personalize option is also added if the |
Table 12-2 shows the behaviors of the different UI artifacts, and the associated methods invoked to execute the behavior.
Table 12-2 UI Artifact Behaviors and Associated Methods
UI Artifact | Class Method Invoked | Event Generated | Comments | |
---|---|---|---|---|
7 |
Delete icon |
During the Invoke Application phase, the method |
|
Deletes a search field from the current |
8 |
Search button |
During the Apply Request Values phase of the JSF lifecycle, a During the Update Model Values phase, the selected operator and the values entered in the search fields are automatically updated to the model using the EL expressions added to the operator and value components (for more information, see Section 12.4.1, "How to Add the Query Component"). These expressions should invoke the During the Invoke Application phase, the You must implement this listener. |
|
Rendered always on the footer (footer contents are not rendered at all when the Performs a query using the select operator and selected Match radio (if no selection is made the default is used), and the values entered for every search field. |
9 |
Reset button |
During the Apply Request Values phase of the JSF lifecycle, a During the Invoke Application phase, the method |
|
Resets the search fields to its previous saved state. |
10 |
Save button |
During the Apply Request Values phase of the JSF lifecycle, a During the Invoke Application phase, the method |
|
Creates a new saved search based on the current saved search settings, including any new search fields added by the user. |
11 |
Add Fields dropdown list |
During the Invoke Application phase, the method |
|
Adds an attribute as a search field to the existing saved search. |
12 |
Mode (Basic or Advanced) button |
During the Apply Request Values phase of the JSF lifecycle, a During the Invoke Application phase, the method changeMode()on the |
|
Clicking the mode button toggles the mode. |
13 |
Delete button |
During the Invoke Application phase, the method |
ActionEvent |
Deletes the selected saved search, unless it is the one currently in use. |
14 |
Apply button |
During the Apply Request Values phase of the JSF lifecycle, a During the Invoke Application phase, the method |
|
Applies changes made to the selected saved search. |
15 |
OK button |
Same as the Apply button. |
|
Applies changes made to the selected saved search and the dialog is closed afterwards. |
16 |
Cancel button |
No method defined for this action. |
|
Cancels any edits made in the dialog. |
The quickQuery
component has one dropdown list that allows a user to select an attribute to search on. The available searchable attributes are drawn from your implementation of the model or from a managed bean. The user can search against the selected attribute or against all attributes.
A quickQuery
component may be used as the starting point of a more complex search using a query
component. For example, the user may perform a quick query search on one attribute, and if successful, may want to continue to a more complex search. The quickQuery
component supports this by allowing you to place command components in the end
facet, which you can bind to a method on a managed bean that allows the user to switch from a quickQuery
to a query
component.
The quickQuery
component renders the searchable criteria in a dropdown list and then, depending on the type of the criteria chosen at runtime, the quickQuery
component renders different criteria fields based on the attribute type. For example, if the attribute type is Number
, it renders an inputNumberSpinbox
component. You do not need to add these components as long as you have implemented the complete model for your query. If instead you have the logic in a managed bean and do not need a complete model, then you create the quickQuery
component artifacts manually. For more information, see Section 12.3.2, "How to Use a quickQuery Component Without a Model."
Implement a QueryModel
class and associated classes. For more information, see Section 12.2, "Implementing the Model for Your Query."
To add a quickQuery component:
In the Component Palette, from the Common Components panel, drag a Quick Query and drop it onto the page.
Expand the Common section of the Property Inspector and set the following attributes:
id: Enter a unique ID for the component.
layout: Specify if you want the component to be displayed horizontally with the criterion and value next to each other, as shown in Figure 12-2, or vertically as shown in Figure 12-5.
model: Enter an EL expression that evaluates to the class that implements the QueryModel
class, as created in Section 12.2, "Implementing the Model for Your Query."
value: Enter an EL expression that evaluates to the class that implements the QueryDescriptor
class, as created in Section 12.2, "Implementing the Model for Your Query."
Expand the Behavior section and set the following attributes:
conjunctionReadOnly: Specify whether or not the user should be able to set the Match Any or Match All radio buttons. When set to false
, the user can set the conjunction. When set to true
, the radio buttons will not be rendered.
queryListener: Enter an EL expression that evaluates to the QueryListener
handler you created in Section 12.2, "Implementing the Model for Your Query."
Drag and drop a table (or other component that will display the search results) onto the page. Set the results component's PartialTriggers
with the ID of the quickQuery
component. The value of this component should resolve to a CollectionModel
object that contains the filtered results.
If you want users to be able to click the Advanced link to turn the quickQuery
component into a full query
component, add a command component to the End
facet of the quickQuery
component, and implement logic that will hide the quickQuery
component and display the query
component.
You can use the quickQuery
component without a model, for example if all your query logic resides in a simple managed bean, including a QueryListener
handler that will execute the search and return the results. You must to manually add and bind the components required to create the complete quickQuery
component.
To add a quickQuery component:
On a managed bean, create a valueChangeListener
handler for the selectOneChoice
component that will display the attributes on which the user can search. The valueChangeListener
handler should handle the choice for which attribute to search on.
On a managed bean, create the QueryListener
handle to execute the search. This handle will use the ID of the input component used to enter the search criterion value, to retrieve the component and the value to execute the query.
In the Component Palette, from the Common Components panel, drag a Quick Query and drop it onto the page.
In the Property Inspector, expand the Common section, and set the following attributes:
id: Enter a unique ID for the component.
layout: Specify if you want the component to display horizontally with the criterion and value next to each other, as shown in Figure 12-2, or vertically, as shown in Figure 12-5.
Expand the Behavior section and set the QueryListener
attribute to an EL expression that evaluates to the QueryListener
handler created in Step 2.
In the Component Palette, from the Common Components panel, drag a Select One Choice and drop it onto the criteriaItems
facet of the quickQuery
component. In the dialog, choose either to enter an EL expression that evaluates to the list of attributes on which the user can search, or to enter a static list. For help with the dialog, press F1 or click Help.
In the Structure window, select the selectOneChoice
component in the criteriaItems
facet, and set the following attributes:
simple: Set to true
so that no label for the component displays.
valueChangeListener: Enter an EL expression that evaluates to the listener created in Step 1.
autoSubmit: Set to true
.
From the Component Palette, add select list items as needed. For more information about using the selectOneChoice
and selectItems
components, see Section 9.6, "Using Selection Components."
In the Component Palette, from the Common Components panel, drag an inputText component as a direct child to the quickQuery
component. Set the following attributes:
simple: Set to true
so that the label is not displayed.
value: Enter an EL expression that evaluates to the property that will contain the value that the user enters.
Tip:
If you do not provide aninputText
component, then at runtime, a disabled inputText
component and a disabled Go icon will be rendered.If you want users to be able to click the Advanced link to turn the quickQuery
component into a full query
component, add a command component to the End
facet of the quickQuery
component, and implement logic that will hide the quickQuery
component and display the query
component.
In the Component Palette, from the Common Components panel, drag a table (or other component that will display the search results) onto the page. Set the results component's PartialTriggers
with the ID of the quickQuery
component. The value of this component should resolve to a CollectionModel
object that contains the filtered results.
When the quickQuery
component is bound to a QueryDescriptor
object, the selectOneChoice
and inputText
components are automatically added at runtime as the page is rendered. However, you can provide your own components. If you do provide both the component to display the searchable attributes and the inputText
components, then you need the QueryListener
handler to get the name-value pair from your components.
If you provide only your own component to show the searchable attributes (and use the default input text component), the framework will display an input text component. You must have your QueryListener
handler get the attribute name from the dropdown list and the value from the QueryDescriptor.getCurrentCriterion()
method to perform the query.
If you provide only your own component to collect the searchable attribute value (and use the default selectOneChoice
component to provide the attribute name), then the framework will display the selectOneChoice
component. You must have your QueryListener
handler get the attribute name from the QueryDescriptor.getCurrentCriterion()
method and the value from your component.
If you choose not to bind the Quick
Query
component value
attribute to a QueryDescriptor
object, and you provide both components, when the Go button is clicked, the framework queues a QueryEvent
event with a null QueryDescriptor
object. The provided QueryListener
handler then executes the query using the changeValueListener
handler to access the name and the input component to access the value. You will need to implement a QueryListener
handler to retrieve the attribute name from your selectOneChoice
component and the attribute value from your inputText
component, and then perform a query.
The query
component is used for full feature searches. It has a basic and an advanced mode, which the user can toggle between by clicking a button.
The features for a basic mode query include:
Dropdown list of selectable search criteria operators
Selectable WHERE
clause conjunction of either AND
or OR
(match all or match any)
Saved (seeded) searches
Personalized saved searches
The advanced mode query form also includes the ability for the user to dynamically add search criteria by selecting from a list of searchable attributes. The user can subsequently delete any criteria that were added.
The user can select from the dropdown list of operators to create a query for the search. The input fields may be configured to be list-of-values (LOV), number spinners, date choosers, or other input components.
To support selecting multiple items from a list, the model must expose a control hint on viewCriteriaItem
and the underlying attribute must be defined as an LOV in the corresponding view object. The hint is used to enable or disable the multiple selection or "in" operator functionality. When multiple selection is enabled, selecting the Equals
or Does not equal
operator will render the search criteria field as a selectManyChoice
component. The user can choose multiple items from the list.
The component for the search criteria field depends on the underlying attribute data type, the operator that was chosen, and whether multiple selection is enabled. For example, a search field for an attribute of type String
with the Contains
operator chosen would be rendered as an inputText
component, as shown in Table 12-3.
If the operator is Equals
or Does not equal
, but multiple selection is not enabled, the component defaults to the component specified in the Default List Type hint from the model.
Table 12-3 Rendered Component for Search Criteria Field of Type String
Operator | Component | Component When Multiple Select Is Enabled |
---|---|---|
|
|
|
|
|
|
|
Default list type hint |
|
|
Default list type hint |
|
|
|
|
|
|
|
|
None |
None |
|
None |
None |
If the underlying attribute is the Number
data type, the component that will be rendered is shown in Table 12-4.
Table 12-4 Rendered Component for Search Criteria Field of Type Number
Operator | Component | Component When Multiple Select Is Enabled |
---|---|---|
|
Default list type hint |
|
|
Default list type hint |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
None |
None |
|
None |
None |
If the underlying attribute is the Date
data type, the component that will be rendered is shown in Table 12-5.
Table 12-5 Rendered Component for Search Criteria Field of Type Date
Operator | Component | Component When Multiple Select Is Enabled |
---|---|---|
|
Default list type hint |
|
Does not equal |
Default list type hint |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
None |
None |
|
None |
None |
If a search criterion's underlying attribute was defined as an LOV, in order for the auto-complete feature to work, the ListOfValues
model instance returned by the getModelList
method of the AttributeCriterion
class must return true
for its isAutoCompleteEnabled
method. For more information about LOV, see Chapter 11, "Using List-of-Values Components."
When autoSubmit
is set to true
, any value change on the search criterion will be immediately pushed to the model. The query component will automatically flush its criterion list only when it has dependent criteria. If the criterion instance has no dependent criteria but autoSubmit
is set to true,
then the query component will be only partially refreshed.
A Match All or Match Any radio button group further modifies the query. A Match All selection is essentially an AND
function. The query will return only rows that match all the selected criteria. A Match Any selection is an OR
function. The query will return all rows that match any one of the criteria items.
After the user enters all the search criteria values (including null values) and selects the Match All or Match Any radio button, the user can click the Search button to initiate the query. The query results can be displayed in any output component. Typically, the output component will be a table or tree table, but you can associate other display components such as af:forms
, af:outputText
, and graphics to be the results component by specifying it in the resultComponentId
attribute.
If the Basic or Advanced button is enabled and displayed, the user can toggle between the two modes. Each mode will display only the search criteria that were defined for that mode. A search criteria field can be defined to appear only for basic, only for advanced, or for both modes.
In advanced mode, the control panel also includes an Add Fields button that exposes a popup list of searchable attributes. When the user selects any of these attributes, a dynamically generated search criteria input field and dropdown operator list is displayed. The position of all search criteria input fields, as well as newly added fields, are determined by the model implementation.
This newly created search criteria field will also have a delete icon next to it. The user can subsequently click this icon to delete the added field. The originally defined search criteria fields do not have a delete icon and therefore cannot be deleted by the user. Figure 12-6 shows an advanced mode query
component with a dynamically added search criteria field named Salary. Notice the delete icon (an X) next to the field.
The user can also save the entered search criteria and the mode by clicking the Save button. A popup dialog allows the user to provide a name for the saved search and specify hints by selecting checkboxes. A persistent data store is required if the saved search is to be available beyond the session. For more information about persistence, see Chapter 31, "Allowing User Customization on JSF Pages."
A seeded search is essentially a saved search that was created by the application developer. When the component is initialized, any seeded searches associated with that query
component become available for the user to select.
Any user-created saved searches and seeded system searches appear in the Saved Search dropdown list. The seeded searches and user-saved searches are separated by a divider.
Users can also personalize the saved and seeded searches for future use. Personalization of saved searches requires the availability of a persistent data store. For more information about persistence, see Chapter 31, "Allowing User Customization on JSF Pages."
Along with the default display described previously, you can also configure the query
component to display in a compact mode, simple mode, or design mode. The compact mode has no header or border, and the Saved Search dropdown list moves next to the expand or collapse icon. Figure 12-7 shows the same query
component as in Figure 12-6, but set to compact mode.
The simple mode displays the component without the header and footer, and without the buttons typically displayed in those areas. Figure 12-8 shows the same query
component set to simple mode.
The design mode has the same visual appearance as the simple mode but is used mostly for designing the QueryDescriptor
.
The query
component supports toolbar
and footer
facets that allow you to add additional components to the query, such as command buttons. For example, you can create command components to toggle between the quickQuery
and query
components and place those in a toolbar in the toolbar
facet.
Implement a QueryModel
class and associated classes. For more information, see Section 12.2, "Implementing the Model for Your Query."
In the Component Palette, from the Common Components panel, drag a Query and drop it onto the page.
In the Property Inspector, expand the Common section and set the following attributes:
id: Set a unique ID for the component.
model: Enter an EL expression that resolves to the QueryModel
class, as created in Section 12.2, "Implementing the Model for Your Query."
value: Enter an EL expression that resolves to the QueryDescriptor
class, as created in Section 12.2, "Implementing the Model for Your Query."
Expand the Appearance section and set the following attributes:
displayMode: Specify if you want the component to display in Default, Simple, Compact, or Design mode.
saveQueryMode: Specify if you want saved searches to be displayed and used at runtime. Set to default
if you want the user to be able to view and edit all saved searches. Set to readOnly
if you want the user to only be able to view and select saved searches, but not update them. Set to hidden
if you do not want any saved searches to be displayed.
modeButtonPosition: Specify if you want the button that allows the user to switch the mode from basic to advanced to be displayed in toolbar (the default) or in the footer
facet.
modeChangeVisible: Set to false
if you want to hide the basic or advanced toggle button.
Expand the Behavior section and set the following:
conjunctionReadOnly: Set to false
if you want the user to be able to select a radio button to determine if the search should match all criteria (query will use the AND
function) or any criteria (query will use the OR
function). When set to true
, the radio buttons will not be rendered.
queryListener: Enter an EL expression that evaluates to the QueryListener
handler, as created in Section 12.2, "Implementing the Model for Your Query."
Expand the Other section and set the following:
criterionFeatures: Enter matchCaseDisplayed
to allow the user to set matchCase
for a criterion. This option is available only for String
data types.
In the Component Palette, from the Common Components panel, drag a table (or other component that will display the search results) onto the page. Set an ID on the table. The value of this component should resolve to a CollectionModel
object that contains the filtered results.
In the Structure window, select the query
component and set the resultComponentID
to the ID of the table.