When data is stored in a database we want to be able to search for records. Searching is so common that DomUI has a special component that helps with creating database search screens: the SearchPanel. The Search Panel works on database objects, i.e. entity classes that are defined in Hibernate or JPA, or even with plain JDBC accessed objects (using DomUI's generic database layer). This means that working with the panel you stay inside the Java world.

Let's start with an example:

@Override public void createContent() throws Exception {
   ContentPanel cp = new ContentPanel();
   add(cp);

   SearchPanel<Invoice> lf = new SearchPanel<>(Invoice.class);
   cp.add(lf);
   lf.setClicked(a -> search(lf));

   lf.add().property("customer").control();        // Start with lookup by customer
   lf.add().property("total").control();           // Allow searching for a total
   lf.add().property("invoiceDate").control();     // And the date.
}

This example creates a search panel which searches for Invoice instances using the customer, total (amount) and invoiceDate properties. The actual searching and showing of the data is done by base class which will be shown at the end of this document.

This fragment creates the following UI (LIVE - click inside to play with it):

<iframe src="https://etc.to/demo/to.etc.domuidemo.pages.searchpanel.SearchPanelManual1.ui" width="1024" height="768"></iframe>

As can be seen, each property is presented on the form, in order. And for each property we have a special "control" which allows for input related to the type of the property. We see, in order:

The SearchPanel uses metadata to get the default label for properties, and it uses a registry of factories (LookupControlRegistry2) to find the best lookup control for a property, by type. The registry can be easily extended with your own lookup control factories.

You can control how data is shown using the builder pattern exhibited above. In that way you can change:

Using metadata with the panel

In the above example we specified what to search on by hand. This is often handy because it allows full control. But the form can also be populated automatically by using the metadata associated with the entity we look for. Take for example the following definition for Invoice's metadata:


@Entity
@Table(name = "Invoice")
@SequenceGenerator(name = "sq", sequenceName = "invoice_sq")
@MetaObject(defaultColumns = {                      // 20180203 Must have metadata for SearchPanel/LookupForm tests.
   @MetaDisplayProperty(name = "customer.lastName", displayLength = 20)
   , @MetaDisplayProperty(name = "customer.firstName", displayLength = 10)
   , @MetaDisplayProperty(name = "invoiceDate")
   , @MetaDisplayProperty(name = "billingAddress", displayLength = 20)
   , @MetaDisplayProperty(name = "billingCity", displayLength = 10)
   , @MetaDisplayProperty(name = "total", displayLength = 10)
}
, searchProperties = {
   @MetaSearchItem(name = "invoiceDate")
   , @MetaSearchItem(name = "billingCity")
   , @MetaSearchItem(name = "customer")
}
)

The searchProperties above are the "default" properties to use inside the SearchPanel, and they take effect when no manual configuration of the SearchPanel is done, like this:

@Override public void createContent() throws Exception {
   ContentPanel cp = new ContentPanel();
   add(cp);

   SearchPanel<Invoice> lf = new SearchPanel<>(Invoice.class);
   cp.add(lf);
   lf.setClicked(a -> search(lf.getCriteria()));
}

In this case the metadata takes effect, resulting in: