Фасеты во фрагментах

Фрагменты поддерживают тот же механизм фасетов, что и экраны. Вы можете использовать предоставляемые фреймворком фасеты внутри фрагментов для добавления переиспользуемой функциональности. Общее введение в фасеты смотрите в разделе Фасеты.

Следующие фасеты доступны для использования во фрагментах:

  • timer – создает клиентский таймер, который может инициировать периодические действия.

  • fragmentSettings – сохраняет настройки UI-компонентов для конкретного пользователя.

  • fragmentDataLoadCoordinator – управляет загрузкой данных во фрагмент.

  • urlQueryParameters – сохраняет состояние UI-компонентов в URL.

Например:

<fragment xmlns="http://jmix.io/schema/flowui/fragment">
<!-- some code -->
    <facets>
        <timer id="timer" delay="1000" autostart="true" repeating="true"/>
        <fragmentSettings auto="true"/>
        <fragmentDataLoadCoordinator auto="true"/>
        <urlQueryParameters>
            <dataGridFilter component="usersDataGrid"/>
            <pagination component="simplePagination"/>
            <propertyFilter component="propertyFilter"/>
            <genericFilter component="genericFilter"/>
        </urlQueryParameters>
    </facets>
    <content>
        <!-- some code -->
    </content>
</fragment>

Некоторые фасеты требуют, чтобы фрагмент имел идентификатор (ID). Вы можете установить его либо в XML с помощью атрибута id, либо программно в контроллере экрана.

settings-fragment-view.xml
<view xmlns="http://jmix.io/schema/flowui/view"
      title="msg://fragmentsettingsfragmentview.title">
    <layout>
        <details id="xmlFacetDetails"
                 summaryText="XML Facet"
                 opened="true"
                 width="100%">
            <fragment id="xmlFragment"
                      class="com.company.onboarding.view.fragments.settingsfragment.SettingsFragment"/> (1)
        </details>
        <details id="javaFacetDetails"
                 summaryText="Java Facet"
                 opened="true"
                 width="100%"/>(2)
    </layout>
</view>
1 Включите фрагмент в экран, используя элемент fragment с атрибутом class, указывающим полное имя класса фрагмента, и атрибутом id, который будет присвоен фрагменту.
2 Контейнер details для программного определения фрагмента в контроллере экрана.

Тот же фрагмент может быть создан программно с использованием бина Fragments. ID устанавливается в методе create():

SettingsFragmentView.java
import com.company.onboarding.view.fragments.settingsfragment.SettingsFragment;
import com.company.onboarding.view.main.MainView;
import com.vaadin.flow.router.Route;
import io.jmix.flowui.Fragments;
import io.jmix.flowui.component.details.JmixDetails;
import io.jmix.flowui.view.*;
import org.springframework.beans.factory.annotation.Autowired;

@Route(value = "settings-fragment-view", layout = MainView.class)
@ViewController(id = "SettingsFragmentView")
@ViewDescriptor(path = "settings-fragment-view.xml")
public class SettingsFragmentView extends StandardView {
    @ViewComponent
    private JmixDetails javaFacetDetails;
    @Autowired
    private Fragments fragments; (1)

    @Subscribe
    public void onInit(final InitEvent event) {
        SettingsFragment javaFragment = fragments.create(this, SettingsFragment.class, "javaFragment"); (2)
        javaFacetDetails.add(javaFragment); (3)
    }
}
1 Инжектирует бин Fragments, который используется для создания фрагментов.
2 Создает экземпляр фрагмента, используя его класс контроллера и ID, который будет присвоен фрагменту.
3 Добавляет экземпляр фрагмента в компонент-контейнер details.

Фасет Timer

Фасет timer создает клиентский элемент таймера. Он использует ту же реализацию, что и таймер на уровне экрана, поэтому все свойства и события работают одинаково во фрагментах.

Пример XML фрагмента:

timer-fragment.xml
<fragment xmlns="http://jmix.io/schema/flowui/fragment">
    <facets>
        <timer id="timer" delay="1000" repeating="true" autostart="true"/>
    </facets>
    <content>
        <vbox id="root">
            <textField id="displayField" readOnly="true"/>
        </vbox>
    </content>
</fragment>

Пример контроллера фрагмента:

TimerFragment.java
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import io.jmix.flowui.component.textfield.TypedTextField;
import io.jmix.flowui.facet.Timer;
import io.jmix.flowui.fragment.Fragment;
import io.jmix.flowui.fragment.FragmentDescriptor;
import io.jmix.flowui.view.Subscribe;
import io.jmix.flowui.view.ViewComponent;

@FragmentDescriptor("timer-fragment.xml")
public class TimerFragment extends Fragment<VerticalLayout> {
    @ViewComponent
    private TypedTextField<String> displayField;

    private int tick;

    @Subscribe("timer")
    public void onTimerTimerAction(final Timer.TimerActionEvent event) {
        displayField.setValue("Timer tick: " + tick++);
    }
}

Фасет Fragment Settings

Фасет fragmentSettings сохраняет настройки для визуальных компонентов. Сохранение происходит при закрытии экрана, аналогично фасету setting для экранов.

Фрагмент, использующий fragmentSettings, должен иметь идентификатор (ID). Вы можете установить его в XML или программно.

Ключевые отличия от настроек экрана:

  • Настройки применяются на событии HostView.ReadyEvent в жизненном цикле фрагмента (вместо ReadyEvent для экранов).

  • Это гарантирует, что настройки будут применены в максимально поздний момент жизненного цикла как экрана, так и фрагмента.

  • Каждый фрагмент на экране хранит свой собственный отдельный набор настроек.

  • Используется выделенный XML-тег fragmentSettings.

Пример XML фрагмента:

settings-fragment.xml
<fragment xmlns="http://jmix.io/schema/flowui/fragment">
    <data>
        <collection id="usersDc"
                    class="com.company.onboarding.entity.User">
            <fetchPlan extends="_base"/>
            <loader id="usersDl" readOnly="true">
                <query>
                    <![CDATA[select e from User e order by e.username]]>
                </query>
            </loader>
        </collection>
    </data>
    <facets>
        <fragmentSettings auto="true"/>
        <fragmentDataLoadCoordinator auto="true"/>
        <urlQueryParameters>
            <pagination component="pagination"/>
        </urlQueryParameters>
    </facets>
    <content>
        <vbox id="root">
            <details id="details" summaryText="Nested details">
                <avatar abbreviation="Jmix"/>
            </details>
            <genericFilter id="genericFilter"
                           dataLoader="usersDl">
                <properties include=".*"/>
            </genericFilter>
            <simplePagination id="pagination" dataLoader="usersDl"
                              itemsPerPageVisible="true" itemsPerPageItems="1, 2, 5, 10"/>
            <dataGrid id="usersDataGrid"
                      width="100%"
                      columnReorderingAllowed="true"
                      minHeight="20em"
                      dataContainer="usersDc">
                <columns resizable="true">
                    <column property="username" filterable="true"/>
                    <column property="firstName" filterable="true"/>
                    <column property="lastName" filterable="true"/>
                    <column property="email" filterable="true"/>
                    <column property="timeZoneId" filterable="true"/>
                    <column property="active" filterable="true"/>
                </columns>
            </dataGrid>
        </vbox>
    </content>
</fragment>

Пример контроллера фрагмента:

SettingsFragment.java
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import io.jmix.flowui.fragment.Fragment;
import io.jmix.flowui.fragment.FragmentDescriptor;

@FragmentDescriptor("settings-fragment.xml")
public class SettingsFragment extends Fragment<VerticalLayout> {
}

Фасет Fragment Data Load Coordinator

Фасет fragmentDataLoadCoordinator управляет загрузкой данных во фрагменте. Например, вы можете установить триггер загрузки на определенные события жизненного цикла фрагмента.

Доступные события жизненного цикла для фрагментов:

  • Fragment.ReadyEvent

  • HostView.InitEvent

  • HostView.BeforeShowEvent

  • HostView.ReadyEvent

Остальная функциональность работает так же, как и фасет dataLoadCoordinator для экранов.

Пример XML фрагмента:

data-load-coordinator-fragment.xml
<fragment xmlns="http://jmix.io/schema/flowui/fragment">
    <data>
        <collection id="usersDc"
                    class="com.company.onboarding.entity.User">
            <fetchPlan extends="_base"/>
            <loader id="usersDl" readOnly="true">
                <query>
                    <![CDATA[select e from User e order by e.username]]>
                </query>
            </loader>
        </collection>
    </data>
    <facets>
        <fragmentDataLoadCoordinator auto="true"/>
    </facets>
    <content>
        <vbox id="root">
            <details id="details" summaryText="Nested details">
                <avatar abbreviation="Jmix"/>
            </details>
            <genericFilter id="genericFilter"
                           dataLoader="usersDl">
                <properties include=".*"/>
            </genericFilter>
            <simplePagination id="pagination" dataLoader="usersDl"
                              itemsPerPageVisible="true" itemsPerPageItems="1, 2, 5, 10"/>
            <dataGrid id="usersDataGrid"
                      width="100%"
                      columnReorderingAllowed="true"
                      minHeight="20em"
                      dataContainer="usersDc">
                <columns resizable="true">
                    <column property="username" filterable="true"/>
                    <column property="firstName" filterable="true"/>
                    <column property="lastName" filterable="true"/>
                    <column property="email" filterable="true"/>
                    <column property="timeZoneId" filterable="true"/>
                    <column property="active" filterable="true"/>
                </columns>
            </dataGrid>
        </vbox>
    </content>
</fragment>

Пример контроллера фрагмента:

DataLoadCoordinatorFragment.java
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import io.jmix.flowui.fragment.Fragment;
import io.jmix.flowui.fragment.FragmentDescriptor;

@FragmentDescriptor("data-load-coordinator-fragment.xml")
public class DataLoadCoordinatorFragment extends Fragment<VerticalLayout> {
}

Фасет Url Query Parameters

Фасет urlQueryParameters сохраняет состояние компонента в URL. Это полезно при использовании подхода "сначала URL" (URL-first) – выход из экрана и возврат в него сохраняет такую информацию, как состояния фильтров.

Фрагмент должен иметь идентификатор (ID), так как его значение используется для сериализации. Вы можете установить ID в XML или программно.

Принцип работы аналогичен фасету urlQueryParameters для экранов.

Пример XML фрагмента:

url-query-parameters-fragment.xml
<fragment xmlns="http://jmix.io/schema/flowui/fragment">
    <data>
        <collection id="usersDc"
                    class="com.company.onboarding.entity.User">
            <fetchPlan extends="_base"/>
            <loader id="usersDl" readOnly="true">
                <query>
                    <![CDATA[select e from User e order by e.username]]>
                </query>
            </loader>
        </collection>
    </data>
    <facets>
        <fragmentDataLoadCoordinator auto="true"/>
        <urlQueryParameters>
            <propertyFilter component="propertyFilter"/>
            <genericFilter component="genericFilter"/>
            <dataGridFilter component="usersDataGrid"/>
            <pagination component="pagination"/>
        </urlQueryParameters>
    </facets>
    <content>
        <vbox id="root">
            <propertyFilter id="propertyFilter" property="username" operation="CONTAINS" dataLoader="usersDl"/>
            <genericFilter id="genericFilter"
                           dataLoader="usersDl">
                <properties include=".*"/>
            </genericFilter>
            <simplePagination id="pagination" dataLoader="usersDl"
                              itemsPerPageVisible="true" itemsPerPageItems="1, 2, 5, 10"/>
            <dataGrid id="usersDataGrid"
                      width="100%"
                      columnReorderingAllowed="true"
                      minHeight="20em"
                      dataContainer="usersDc">
                <columns resizable="true">
                    <column property="username" filterable="true"/>
                    <column property="firstName" filterable="true"/>
                    <column property="lastName" filterable="true"/>
                    <column property="email" filterable="true"/>
                    <column property="timeZoneId" filterable="true"/>
                    <column property="active" filterable="true"/>
                </columns>
            </dataGrid>
        </vbox>
    </content>
</fragment>

Пример контроллера фрагмента:

UrlQueryParametersFragment.java
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import io.jmix.flowui.fragment.Fragment;
import io.jmix.flowui.fragment.FragmentDescriptor;

@FragmentDescriptor("url-query-parameters-fragment.xml")
public class UrlQueryParametersFragment extends Fragment<VerticalLayout> {
}