urlQueryParameters
urlQueryParameters
facet is designed for declarative binding of the view state to the URL. It allows you to preserve the view state when navigating between views or refreshing the browser page.
If the entire view state comes from the database, which is the case for entity detail views, the entity identifier in the URL route is enough to restore the state. But if some view components contain values that are not stored in the database, you need to encode them in the URL to restore when the view is reinitialised.
The obvious example is the entity list view with pagination and filtering. You will want to preserve pagination and filtering parameters when refreshing the browser page and when navigating to a detail view and back.
The entire view state encoded in the URL also provides a deep link representing exactly what is shown on the screen.
Basic Usage
To bind pagination and filtering parameters to the URL, define urlQueryParameters
and use nested elements to connect existing components by their identifiers. In the following example, the urlQueryParameters
facet is used with genericFilter
and simplePagination
components:
<facets>
<urlQueryParameters id="urlQueryParameters">
<pagination component="pagination"/>
<genericFilter component="genericFilter"/>
</urlQueryParameters>
</facets>
<layout expand="usersTable">
<genericFilter id="genericFilter"
dataLoader="usersDl">
<properties include=".*"/>
</genericFilter>
<hbox id="buttonsPanel" classNames="buttons-panel">
<!-- ... -->
<simplePagination id="pagination" dataLoader="usersDl"/>
</hbox>
As a result, filtering the User
entity list view by the active
attribute and selecting the second page will be reflected in the URL like this:
http://localhost:8080/users?genericFilterCondition=property%3Aactive_equal_true&maxResults=50&firstResult=100
You can view and edit facet attributes in Jmix Studio using the Jmix UI inspector panel. |
Supported Components
pagination
The pagination
nested element allows you to connect the urlQueryParameters
facet to the simplePagination component.
Attributes of the pagination
element:
-
component
- identifier of the pagination component to connect to. -
firstResultParam
- (optional) name of the query parameter for representing the beginning of the current page. -
maxResultsParam
- (optional) name of the query parameter for representing the page size.
propertyFilter
The propertyFilter
nested element allows you to connect the urlQueryParameters
facet to the propertyFilter component.
Attributes of the propertyFilter
element:
-
component
- identifier of thepropertyFilter
component to connect to. -
param
- (optional) name of the query parameter for representing the filter value.
genericFilter
The genericFilter
nested element allows you to connect the urlQueryParameters
facet to the genericFilter
component.
Attributes of the genericFilter
element:
-
component
- identifier of thegenericFilter
component to connect to. -
conditionParam
- (optional) name of the query parameter for representing the filter conditions. -
configurationParam
- (optional) name of the query parameter for representing the selected filter configuration.
Custom State Binding
The urlQueryParameters
facet allows you to bind any custom view state to the URL.
Let’s consider an example of a view with the following components:
<details id="sampleDetails" summaryText="Some details">
<textField id="sampleTextField" datatype="string"/>
</details>
Imagine that the goal is to preserve the opened
state of the details layout and the value of the textField.
Then you need to implement a binder object and register it in the urlQueryParameters
facet:
private static final String DETAILS_OPENED_URL_PARAM = "detailsOpened";
private static final String TEXT_URL_PARAM = "text";
@ViewComponent
private UrlQueryParametersFacet urlQueryParameters;
@ViewComponent
private JmixDetails sampleDetails;
@ViewComponent
private TypedTextField<String> sampleTextField;
private class SampleUrlQueryParametersBinder extends AbstractUrlQueryParametersBinder { (1)
public SampleUrlQueryParametersBinder() { (2)
sampleDetails.addOpenedChangeListener(event -> {
boolean opened = event.isOpened();
QueryParameters qp = new QueryParameters(ImmutableMap.of(DETAILS_OPENED_URL_PARAM,
opened ? Collections.singletonList("1") : Collections.emptyList()));
fireQueryParametersChanged(new UrlQueryParametersFacet.UrlQueryParametersChangeEvent(this, qp));
});
sampleTextField.addValueChangeListener(event -> {
String text = event.getValue();
QueryParameters qp = new QueryParameters(ImmutableMap.of(TEXT_URL_PARAM,
text != null ? Collections.singletonList(text) : Collections.emptyList()));
fireQueryParametersChanged(new UrlQueryParametersFacet.UrlQueryParametersChangeEvent(this, qp));
});
}
@Override
public void updateState(QueryParameters queryParameters) { (3)
List<String> detailsOpenedStrings = queryParameters.getParameters().get(DETAILS_OPENED_URL_PARAM);
if (detailsOpenedStrings != null) {
sampleDetails.setOpened("1".equals(detailsOpenedStrings.get(0)));
}
List<String> textStrings = queryParameters.getParameters().get(TEXT_URL_PARAM);
if (textStrings != null && !textStrings.isEmpty()) {
sampleTextField.setValue(textStrings.get(0));
}
}
}
@Subscribe
public void onInit(final InitEvent event) {
urlQueryParameters.registerBinder(new SampleUrlQueryParametersBinder()); (4)
}
1 | - inherit the binder class from the AbstractUrlQueryParametersBinder base class. |
2 | - in the binder’s constructor, add component listeners that will invoke the fireQueryParametersChanged() method of the binder when the components' state changes. |
3 | - in the binder’s updateState() method, update the state of the components. |
4 | - create the binder instance and register it in the urlQueryParameters facet on view initialization. |
The urlQueryParameters facet uses QueryParameters class from the Vaadin API to send and receive the query parameters.
|