Page tree

Versions Compared


  • This line was added.
  • This line was removed.
  • Formatting was changed.


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

<iframe src="" width="1024" height="768">

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 customer property uses a LookupInput2, because it is actually a @ManyToOne relation (parent) of the Invoice class. This control lets you search for a Customer using a special UI.
  • The "total" field is a numeric field. It uses a special Lookup Control called NumberLookupControl which allows searching for a number as follows:
    • Enter "> 1000" to find all records with an amount > 1000. Likewise you can use <, <=, >=.
    • Entering a single amount searches for an exact match
    • Entering 10% does a "like" query with all amounts that start by 10.
  • The invoiceDate field creates another Lookup Control called DateLookupControl. This control shows two dates, and allows searched starting from, ending at or between the two dates.

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:

  • The label by using label(String) or label(NodeContainer)
  • The lookup hint (what is shown when hovering over the control) which also defaults to metadata
  • The default value to use. This value will be used as the initial value of the control, and will also be used when the "reset" button is pressed on the panel.
  • Whether a text search ignores case or not (defaults to true)
  • The minimal input length for a control before the search is issued. This can be used to prevent large searches by specifying that at least 3 characters should be used for instance.
  • Options specific for the control being created.

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:

Code Block
@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:

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

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

In this case the metadata takes effect, resulting in: