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 the propertyFilter 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 the genericFilter 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));
        }
    }

    @Override
    public Component getComponent() {
        return null;
    }
}

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