12 Using Query Components

This chapter describes how to use the query and quickQuery search panel components.

This chapter includes the following sections:

12.1 Introduction to Query Components

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 quickQuery 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.

Figure 12-1 Query Component with Three Search Criteria

ADF Faces 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.

Figure 12-2 A QuickQuery Component in Horizontal Layout

Horizontal quick query component

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 own QueryModel 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

  • Toggling between the basic and advanced mode

  • 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.

12.2 Implementing the Model for Your Query

Before you can use the query components, you must to create your QueryModel classes.

Tip:

You can use the quickQuery 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.

Figure 12-3 Class Diagram for QueryModel

Class diagram for query model.

To create the model classes:

  1. 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.
  2. 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.

    Example 12-1 A QueryListener Handler Method

      public void processQuery(QueryEvent event)
      {
        DemoQueryDescriptor descriptor = (DemoQueryDescriptor) event.getDescriptor();
        String sqlString = descriptor.getSavedSearchDef().toString();
        setSqlString(sqlString);
      }
    

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.

Figure 12-4 Query Component and Associated Popup Dialog

query component’s buttons and fields

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 QueryDescriptor instance provides the items displayed in the panel.

Based on a saved search.

2

Disclosure icon

 

Opens or closes the search panel

3

Match type radio button

Available through the getConjunction() method on the ConjunctionCriterion class.

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 All conjunction type is used between all the search fields, then All appears selected. If it is a mix of All and Any, then none of the radio buttons appears selected.

The Match Type will be read only if the conjunctionReadOnly property is set to true. Its not rendered at all when the displayMode attribute is set to simple.

4

Group of search fields

The collection of search fields for a QueryDescriptor object is represented by a ConjunctionCriterion object, returned by the method getConjunctionCriterion() on the QueryDescriptor class. The getCriterionList() method returns a List<Criterion> list.

Displays one or more search fields associated with the currently selected search.

5

Search field

An AttributeCriterion class provides information specific to a search field instance. An AttributeCriterion object is an item in the List<Criterion> list returned by getCriterionList() method on the ConjunctionCriterion class (see #4).

An AttributeDescriptor class provides static information pertaining to a search field. This is available through the method getAttribute(), on the AttributeCriterion class.

The getConverter() method of the AttributeDescriptor class can be overridden to return a converter object of type javax.faces.convert.Converter. When defined, the attribute value is converted using this converter instance. The default return value is null.

The hasDependentCriterion method in the AttributeCriterion class returns true if the criterion has dependents. If the criterion has dependents, then the dependent criterion fields are refreshed when the value for this criterion changes. By default this method returns false.

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 Employee and Salary attributes. Even though both saved searches are based on the same attributes of the Employee object, the search field Salary is configured to have its default operator as less than and value as 50000.00 for the low Salaried Employees search and for the High Salaried Employees search, with a default operator of greater than and value of 100000.00. Selecting the saved searches on the UI will show the appropriate operator and values for that search.

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 getSystemQueries() and getUserQueries() on the QueryModel class.

Displays a list of available system- and user-saved searches.

A Personalize option is also added if the saveQueryMode property is set to default. Selecting this option opens a Personalize dialog, which allows users to personalize saved searches. They can duplicate or update an existing saved search.


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 removeCriterion() on the QueryDescriptor class is called automatically by an internal ActionListener handler registered with the command component.

ActionEvent

Deletes a search field from the current QueryDescriptor object.

8

Search button

During the Apply Request Values phase of the JSF lifecycle, a QueryEvent event is queued, to be broadcast during the Invoke Application phase.

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 get/setOperator(); get/setOperators(); and getValues() methods, respectively, on the AttributeCriterion class.

During the Invoke Application phase, the QueryListener registered with the query component is invoked and this performs the search.

You must implement this listener.

QueryEvent

Rendered always on the footer (footer contents are not rendered at all when the displayMode attribute is simple)

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 QueryOperationEvent event is queued with the operation type QueryOperationEvent. Operation.RESET, to be broadcast during the Invoke Application phase.

During the Invoke Application phase, the method reset() on the QueryModel class is called. This is done automatically by an internal QueryOperationListener handler registered with the query component. You must override this method to reset the QueryDescriptor object to its original state.

QueryOperationEvent (an internal QueryOperation Listener handler is registered with the query component that in turn calls the model methods).

Resets the search fields to its previous saved state.

10

Save button

During the Apply Request Values phase of the JSF lifecycle, a QueryOperationEvent event is queued with the operation type QueryOperationEvent. Operation.SAVE, to be broadcast during the Invoke Application phase.

During the Invoke Application phase, the method create() on the QueryModel class is called. After the call to the create() method, the update() method is called to save the hints (selected by the user in the dialog) onto the new saved search. This is done automatically by an internal QueryOperationListener handler registered with the query component. You must override this method to create a new object based on the argument passed in.

QueryOperationEvent (an internal QueryOperation Listener handler is registered with the query component that in turn calls the model methods).

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 addCriterion() on the QueryDescriptor class is called automatically by an internal ActionListener handler registered with the command component. You must override this method to create a new AttributeCriterion object based on the AttributeDescriptor object (identified by the name argument).

ActionEvent

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 QueryOperationEvent event is queued with the operation type QueryOperationEvent. Operation.MODE_CHANGE, to be broadcast during the Invoke Application phase.

During the Invoke Application phase, the method changeMode()on the QueryModel class is called.

QueryOperationEvent (an internal QueryOperation Listener handler is registered with the query component that in turn calls the model methods).

Clicking the mode button toggles the mode.

13

Delete button

During the Invoke Application phase, the method delete() on the QueryModel class is called. This is done automatically by an internal QueryOperationListener handler registered with the query component. You must override this method order to delete the QueryDescriptor object.

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 QueryOperationEvent event is queued with the operation type QueryOperationEvent. Operation.UPDATE, to be broadcast during the Invoke Application phase.

During the Invoke Application phase, the method update() on the QueryModel class is called. This is done automatically by an internal QueryOperationListener handler registered with the query component. You must override this method in order to update the QueryDescriptor object using the arguments passed in.

QueryOperationEvent (an internal QueryOperation Listener is registered with the query component that in turn calls the model methods).

Applies changes made to the selected saved search.

15

OK button

Same as the Apply button.

QueryOperationEvent (an internal QueryOperation Listener handler is registered with the query component that in turn calls the model methods).

Applies changes made to the selected saved search and the dialog is closed afterwards.

16

Cancel button

No method defined for this action.

QueryOperationEvent (an internal QueryOperation Listener handler is registered with the query component that in turn calls the model methods).

Cancels any edits made in the dialog.


12.3 Using the quickQuery Component

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."

12.3.1 How to Add the quickQuery Component Using a Model

Before you begin

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:

  1. In the Component Palette, from the Common Components panel, drag a Quick Query and drop it onto the page.

  2. Expand the Common section of the Property Inspector and set the following attributes:

  3. 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."

  4. 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.

  5. 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.

12.3.2 How to Use a quickQuery Component Without a Model

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:

  1. 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.

  2. 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.

  3. In the Component Palette, from the Common Components panel, drag a Quick Query and drop it onto the page.

  4. 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.

  5. Expand the Behavior section and set the QueryListener attribute to an EL expression that evaluates to the QueryListener handler created in Step 2.

  6. 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.

  7. 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.

  8. 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."

  9. 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 an inputText component, then at runtime, a disabled inputText component and a disabled Go icon will be rendered.
  10. 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.

  11. 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.

12.3.3 What Happens at Runtime: How the Framework Renders the quickQuery Component and Executes the Search

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 QuickQuery 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.

12.4 Using the query Component

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

Starts with

af:inputText

af:inputText

Ends with

af:inputText

af:inputText

Equals

Default list type hint

af:selectManyChoice

Does not equal

Default list type hint

af:selectManyChoice

Contains

af:inputText

af:inputText

Does not contain

af:inputText

af:inputText

Is blank

None

None

Is not blank

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

Equals

Default list type hint

af:selectManyChoice

Does not equal

Default list type hint

af:selectManyChoice

Less than

af:inputNumberSpinBox

af:inputNumberSpinBox

Less than or equal to

af:inputNumberSpinBox

af:inputNumberSpinBox

Greater than

af:inputNumberSpinBox

af:inputNumberSpinBox

Greater than or equal to

af:inputNumberSpinBox

af:inputNumberSpinBox

Between

af:inputNumberSpinBox

af:inputNumberSpinBox

Not between

af:inputNumberSpinBox

af:inputNumberSpinBox

Is blank

None

None

Is not blank

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

Equals

Default list type hint

af:selectManyChoice

Does not equal

Default list type hint

af:selectManyChoice

Before

af:inputDate

af:inputDate

After

af:inputDate

af:inputDate

On or before

af:inputDate

af:inputDate

On or after

af:inputDate

af:inputDate

Between

af:inputDate (2)

af:inputDate (2)

Not between

af:inputDate (2)

af:inputDate (2)

Is blank

None

None

Is not blank

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.

Figure 12-6 Advanced Mode Query with Dynamically Added Search Criteria

Dynamic search criteria

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.

Figure 12-7 Query Component in Compact Mode

Query Component in 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.

Figure 12-8 Query Component in Simple Mode

Query Component in 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.

12.4.1 How to Add the Query Component

Before you begin:

Implement a QueryModel class and associated classes. For more information, see Section 12.2, "Implementing the Model for Your Query."

To add a query component:

  1. In the Component Palette, from the Common Components panel, drag a Query and drop it onto the page.

  2. In the Property Inspector, expand the Common section and set the following attributes:

  3. 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.

  4. 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."

  5. 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.

  6. 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.

  7. In the Structure window, select the query component and set the resultComponentID to the ID of the table.