3.5.4.3. DataLoadCoordinator

DataLoadCoordinator facet is designed for declarative linking of data loaders to data containers, visual components and screen events. It can work in two modes:

  • In automatic mode, it relies on parameter names with special prefixes. The prefix denotes a component which produces the parameter value and change events. If the loader has no parameters in its query text (although it can have parameters in query conditions), it is refreshed on BeforeShowEvent in Screen or on AttachEvent in ScreenFragment.

    By default, the parameter prefix is container_ for data containers and component_ for visual components.

  • In manual mode, the links are specified in the facet markup or via its API.

Semi-automatic mode is also possible, when some links are specified explicitly and the rest is configured automatically.

When using DataLoadCoordinator in a screen, the @LoadDataBeforeShow annotation on the screen controller has no effect: the loading of data is controlled by the facet and by custom event handlers, if any.

See usage examples below.

  1. Automatic configuration. The auto attribute is set to true.

    <window xmlns="http://schemas.haulmont.com/cuba/screen/window.xsd"
            xmlns:c="http://schemas.haulmont.com/cuba/screen/jpql_condition.xsd" ...>
        <data readOnly="true">
            <collection id="ownersDc" class="com.company.demo.entity.Owner" view="owner-view">
                <loader id="ownersDl">
                    <query>
                        <![CDATA[select e from demo_Owner e]]> (1)
                        <condition>
                            <and>
                                <c:jpql>
                                    <c:where>e.category = :component_categoryFilterField</c:where> (2)
                                </c:jpql>
                                <c:jpql>
                                    <c:where>e.name like :component_nameFilterField</c:where> (3)
                                </c:jpql>
                            </and>
                        </condition>
                    </query>
                </loader>
            </collection>
            <collection id="petsDc" class="com.company.demo.entity.Pet">
                <loader id="petsDl">
                    <query><![CDATA[select e from demo_Pet e where e.owner = :container_ownersDc]]></query> (4)
                </loader>
            </collection>
        </data>
        <facets>
            <dataLoadCoordinator auto="true"/>
        </facets>
        <layout>
            <pickerField id="categoryFilterField" metaClass="demo_OwnerCategory"/>
            <textField id="nameFilterField"/>
    1 - there are no parameters in the query, so the ownersDl loader will be triggered on BeforeShowEvent.
    2 - the ownersDl loader will also be triggered on categoryFilterField component value change.
    3 - the ownersDl loader will also be triggered on nameFilterField component value change. As the condition uses the like clause, the value will be automatically wrapped in '(?i)% %' to provide the case-insensitive search.
    4 - the petsDl is triggered on the ownersDc data container item change.
  2. Manual configuration. The auto attribute is absent (or set to false), the nested entries define when the data loaders must be triggered.

    <window xmlns="http://schemas.haulmont.com/cuba/screen/window.xsd"
            xmlns:c="http://schemas.haulmont.com/cuba/screen/jpql_condition.xsd" ...>
        <data readOnly="true">
            <collection id="ownersDc" class="com.company.demo.entity.Owner" view="owner-view">
                <loader id="ownersDl">
                    <query>
                        <![CDATA[select e from demo_Owner e]]>
                        <condition>
                            <and>
                                <c:jpql>
                                    <c:where>e.category = :category</c:where>
                                </c:jpql>
                                <c:jpql>
                                    <c:where>e.name like :name</c:where>
                                </c:jpql>
                            </and>
                        </condition>
                    </query>
                </loader>
            </collection>
            <collection id="petsDc" class="com.company.demo.entity.Pet">
                <loader id="petsDl">
                    <query><![CDATA[select e from demo_Pet e where e.owner = :owner]]></query>
                </loader>
            </collection>
        </data>
        <facets>
            <dataLoadCoordinator>
                <refresh loader="ownersDl"
                         onScreenEvent="Init"/> (1)
    
                <refresh loader="ownersDl" param="category"
                         onComponentValueChanged="categoryFilterField"/> (2)
    
                <refresh loader="ownersDl" param="name"
                         onComponentValueChanged="nameFilterField" likeClause="CASE_INSENSITIVE"/> (3)
    
                <refresh loader="petsDl" param="owner"
                         onContainerItemChanged="ownersDc"/> (4)
            </dataLoadCoordinator>
        </facets>
        <layout>
            <pickerField id="categoryFilterField" metaClass="demo_OwnerCategory"/>
            <textField id="nameFilterField"/>
    1 - the ownersDl loader will be triggered on InitEvent.
    2 - the ownersDl loader will also be triggered on categoryFilterField component value change.
    3 - the ownersDl loader will also be triggered on nameFilterField component value change. The likeClause attribute causes the value to be wrapped in '(?i)% %' to provide the case-insensitive search.
    4 - the petsDl is triggered on the ownersDc data container item change.
  3. Semi-automatic configuration. When the auto attribute is set to true and there are some manually configured triggers, the facet will configure automatically all loaders that have no manual configuration.

    <window xmlns="http://schemas.haulmont.com/cuba/screen/window.xsd" ...>
        <data readOnly="true">
            <collection id="ownersDc" class="com.company.demo.entity.Owner" view="owner-view">
                <loader id="ownersDl">
                    <query>
                        <![CDATA[select e from demo_Owner e]]>
                    </query>
                </loader>
            </collection>
            <collection id="petsDc" class="com.company.demo.entity.Pet">
                <loader id="petsDl">
                    <query><![CDATA[select e from demo_Pet e where e.owner = :container_ownersDc]]></query> (1)
                </loader>
            </collection>
        </data>
        <facets>
            <dataLoadCoordinator auto="true">
                <refresh loader="ownersDl" onScreenEvent="Init"/> (2)
            </dataLoadCoordinator>
        </facets>
    1 - the petsDl is configured automatically and triggered on the ownersDc data container item change.
    2 - the ownersDl loader is configured manually and will be triggered on InitEvent.