EntitySuggestionField
EntitySuggestionField
allows searching for entity instances according to a string entered by a user. It performs actions when a user clicks buttons on the right.
EntitySuggestionField
is an input field with the additional functionality: a user enters a few characters, and if several matches have been found, a drop-down list will display all of them. EntitySuggestionField
refreshes the list of options on each entered symbol.
The list of options is loaded in the background according to the logic defined by the application developer on the server-side.
In fact, EntitySuggestionField
is a hybrid of SuggestionField and EntityPicker.
Component’s XML-name: entitySuggestionField
.
Basics
Use EntitySuggestionField
if:
-
Users need to select a single entity instance.
-
The number of options in the list of suggested values is too large to use EntityComboBox.
-
You want to provide high-performance search in the database without loading much data to the UI layer.
To create EntitySuggestionField
connected to data, use the dataContainer and property attributes and the query element:
<data>
<instance id="addressDc" class="ui.ex1.entity.Address"> (1)
<fetchPlan extends="_base"> (2)
<property name="country" fetchPlan="_instance_name"/>
<property name="city" fetchPlan="_base">
<property name="country" fetchPlan="_base"/>
</property>
</fetchPlan>
</instance>
</data>
<layout>
<vbox spacing="true">
<entitySuggestionField id="countryField"
inputPrompt="msg://entitySuggestionField/select"
caption="msg://ui.ex1.entity/Address.country"
dataContainer="addressDc"
property="country">
<query entityClass="ui.ex1.entity.Country"
searchStringFormat="%${searchString}%"
escapeValueForLike="true"
fetchPlan="_instance_name">
<![CDATA[select c from uiex1_Country c where lower(c.name)
like lower(:searchString) escape '\']]>
</query>
</entitySuggestionField>
</vbox>
</layout>
1 | InstanceContainer for the Address entity. |
2 | Inline fetch plan of the entity instance located in the container. |
The screen defines the addressDc
data container for the Address
entity having the country
attribute in the example above. In the entitySuggestionField
element, the dataContainer
attribute contains a link to the addressDc
data container, and the property
attribute refers to the country
entity attribute. The entity attribute should be a reference to an entity. In our example, it is Country
.
Defining Options
You can specify a list of options either in the XML descriptor using the query
nested element or programmatically in the controller using the SearchExecutor
interface.
query
query
is an optional element that enables defining a query for selecting suggested values.
The query
element has the following attributes:
-
entityClass
(required) - a full qualified name of an entity class.
-
fetchPlan
- an optional attribute that specifies the fetch plan to be used for loading the queried entity.
-
escapeValueForLike
- enables searching for the values that contain special symbols:%
,\
, etc. The default value isfalse
.
-
searchStringFormat
- a Groovy string; thus, you can use any valid Groovy-string expressions.
SearchExecutor
If query
is not defined, you should programmatically set the list of options using SearchExecutor
.
SearchExecutor
is a functional interface that contains a single method: List<E> search(String searchString, Map<String, Object> searchParams)
.
Use the searchString
parameter to filter candidates using the string entered by the user.
First, declare a component in the XML descriptor:
<entitySuggestionField id="entityField"
dataContainer="addressDc"
property="country"
caption="Country"/>
Then set SearchExecutor
to the component:
@Autowired
private DataManager dataManager;
@Install(to = "entityField", subject = "searchExecutor")
private List entityFieldSearchExecutor(String searchString,
Map<String, Object> searchParams) {
return dataManager.load(Country.class)
.query("e.name like ?1 order by e.name", "(?i)%" + searchString + "%")
.list();
}
You can generate the |
The |
You can use the escapeForLike()
method to search for the values that contain special symbols:
@Autowired
private DataManager dataManager;
@Install(to = "entitySuggestionField", subject = "searchExecutor")
private List<Customer> entitySuggestionFieldSearchExecutor(String searchString,
Map<String, Object> searchParams) {
searchString = QueryUtils.escapeForLike(searchString);
return dataManager.load(Customer.class)
.query("e.firstName like ?1 escape '\\' order by e.firstName", "(?i)%"
+ searchString + "%")
.list();
}
metaClass
You can use EntitySuggestionField
without binding to the data container, that is, without setting dataContainer
and property
. In this case, use the metaClass
attribute to specify an entity type for EntitySuggestionField
. For example:
<entitySuggestionField id="metaClassField"
metaClass="uiex1_Country"
caption="Country"/>
The search logic is defined using SearchExecutor:
@Autowired
private DataManager dataManager;
@Install(to = "metaClassField", subject = "searchExecutor")
private List<Country> metaClassFieldSearchExecutor(String searchString,
Map<String, Object> searchParams) {
return dataManager.load(Country.class)
.query("e.name like ?1 order by e.name", "(?i)%" + searchString + "%")
.list();
}
Actions
You can define custom and predefined actions for EntitySuggestionField
displayed as buttons on the right.
You can do it either in the XML descriptor using the actions
nested element or programmatically in the controller using the addAction()
method.
Predefined Actions
If you create EntitySuggestionField
without actions, the XML loader will define only the entity_lookup
and entity_open
actions. There are also the entity_clear
and entity_openComposition
actions.
To add other predefined action, for example, the entity_clear
, you should specify the actions
element as follows:
<entitySuggestionField dataContainer="addressDc"
property="country"
caption="Country">
<actions>
<action id="lookup" type="entity_lookup"/>
<action id="open" type="entity_open"/>
<action id="clear" type="entity_clear"/>
</actions>
</entitySuggestionField>
The actions
element does not extend but overrides a set of standard actions. You should define the identifiers of all required actions explicitly.
Use addAction()
to set actions programmatically. If the component is defined in the XML descriptor without actions
nested element, it is sufficient to add missing actions:
@Autowired
private EntitySuggestionField<Country> entitySuggestionField;
@Autowired
private Actions actions;
@Subscribe
public void onInit(InitEvent event) {
entitySuggestionField.addAction(actions.create(EntityClearAction.class));
}
Custom Actions
Custom actions for EntitySuggestionField
are similar to custom actions for EntityPicker
.
Events and Handlers
To generate a handler stub in Jmix Studio, select the component in the screen descriptor XML or in the Component Hierarchy panel and use the Handlers tab of the Component Inspector panel. Alternatively, you can use the Generate Handler button in the top panel of the screen controller. |
ArrowDownHandler
ArrowDownEvent
is fired when a user presses Arrow Down key when the popup with suggestions is hidden.
You can set up your own action handler and use EntitySuggestionField.showSuggestions()
method, which accepts the list of entities to show suggestions:
@Autowired
private CollectionContainer<Country> countriesDc;
@Autowired
private EntitySuggestionField<Country> countryField;
@Install(to = "countryField", subject = "arrowDownHandler")
private void countryFieldArrowDownHandler(SuggestionFieldComponent.ArrowDownEvent
arrowDownEvent) {
countryField.showSuggestions(new ArrayList<>(countriesDc.getItems()));
}
EnterPressHandler
See the example of programmatic registration in the Handling User Input section for ComboBox
.
EnterPressHandler
can be provided declaratively using the @Install
annotation in the screen controller. See this example in the Handling User Input section for EntityComboBox
.
FieldIconProvider
See FieldIconProvider.
Formatter
Adds a formatter instance to the component.
In the example below, we will show a formatter
usage for the cityFieldFormat
entity suggestion field:
@Install(to = "cityFieldFormat", subject = "formatter")
protected String cityFieldFormatFormatter(City value) {
return value != null
? value.getName() + " (" + (value.getCountry() != null
? value.getCountry().getName() : "not defined") + ")"
: null;
}
To add a formatter programmatically, use the addFormatter()
component method.
SearchExecutor
See SearchExecutor.
Validator
See Validator.
ValueChangeEvent
See ValueChangeEvent.
EntitySuggestionField XML Attributes
You can view and edit attributes applicable to the component using the Component Inspector panel of the Studio’s Screen Designer. |
align - asyncSearchDelayMs - caption - captionAsHtml - captionProperty - colspan - contextHelpText - contextHelpTextHtmlEnabled - css - dataContainer - description - descriptionAsHtml - editable - enable - box.expandRatio - height - htmlSanitizerEnabled - icon - id - inputPrompt - metaClass - minSearchStringLength - popupWidth - property - required - requiredMessage - responsive - rowspan - stylename - suggestionsLimit - tabIndex - visible - width
EntitySuggestionField XML Elements
actions - formatter - query - validators