Использование фрагментов
Этот раздел объясняет, как определять и использовать фрагменты. См. также раздел События фрагмента.
Декларативное использование
Предположим, у вас есть фрагмент для ввода адреса:
@FragmentDescriptor("address-fragment.xml")
public class AddressFragment extends Fragment<FormLayout> {
}<fragment xmlns="http://jmix.io/schema/flowui/fragment">
    <content>
        <formLayout>
            <textField id="cityField" label="City"/>
            <textField id="zipcodeField" label="Zipcode"/>
        </formLayout>
    </content>
</fragment>| Фрагмент можно создать с помощью мастера создания экранов в Студии. Выберите шаблон Blank fragmentиз списка шаблонов экранов. | 
Фрагмент можно включить в экран, используя элемент fragment с атрибутом class, в котором указан FQN класса фрагмента:
<view xmlns="http://jmix.io/schema/flowui/view">
    <layout>
        <details id="addressDetails" summaryText="Address" opened="true" alignSelf="STRETCH">
            <fragment class="com.company.onboarding.view.address.var1.AddressFragment"/>
        </details>
    </layout>
</view>Элемент fragment может быть добавлен к любому UI-контейнеру экрана, включая элемент layout верхнего уровня.
| В визуальном дизайнере Studio используйте действие Add Component, чтобы открыть палитру компонентов. Найдите в ней компонент Fragmentи перетащите его в структуру компонентов или в XML. | 
Программное использование
Этот же фрагмент может быть включен в экран программно используя бин Fragments, например:
<view xmlns="http://jmix.io/schema/flowui/view">
    <layout>
        <details id="addressDetails" summaryText="Address" opened="true" alignSelf="STRETCH"/>
    </layout>
</view>@Route(value = "HostView", layout = MainView.class)
@ViewController("HostView")
@ViewDescriptor("host-view.xml")
public class HostView extends StandardView {
    @ViewComponent
    private Details addressDetails;
    @Autowired
    private Fragments fragments; (1)
    @Subscribe
    public void onInit(InitEvent event) {
        AddressFragment addressFragment = fragments.create(this, AddressFragment.class); (2)
        addressDetails.add(addressFragment); (3)
    }
}| 1 | Инжекция бина Fragments, который предназначен для создания фрагментов. | 
| 2 | Создание экземпляра фрагмента по его классу. | 
| 3 | Добавление экземпляра фрагмента в компонент Details. | 
| Если фрагмент подписан на событие хост-экрана, то фрагмент должен быть создан и добавлен в экран перед тем, как это событие будет вызвано. | 
Передача параметров в фрагменты
Контроллер фрагмента может иметь публичные сеттеры для принятия параметров, как это делается при открытии экранов, например:
@FragmentDescriptor("address-fragment.xml")
public class AddressFragment extends Fragment<FormLayout> {
    @ViewComponent
    private EntityComboBox<City> cityField;
    @ViewComponent
    private TypedTextField<String> zipcodeField;
    public void setCitiesContainer(CollectionContainer<City> citiesContainer) { (1)
        cityField.setItems(citiesContainer);
    }
    public void setZipcodePlaceholder(String placeholder) {
        zipcodeField.setPlaceholder(placeholder);
    }
}| 1 | Сеттеры позволяют передавать параметры во фрагмент. | 
Если фрагмент добавляется в экран декларативно в XML, используйте элемент properties для передачи параметров, например:
<view xmlns="http://jmix.io/schema/flowui/view">
    <data>
        <collection id="citiesDc"
                    class="com.company.onboarding.entity.City">
            <fetchPlan extends="_base"/>
            <loader id="citiesDl" readOnly="true">
                <query>
                    <![CDATA[select e from City e]]>
                </query>
            </loader>
        </collection>
    </data>
    <facets>
        <dataLoadCoordinator auto="true"/>
    </facets>
    <layout>
        <details id="addressDetails" summaryText="Address" opened="true" alignSelf="STRETCH">
            <fragment class="com.company.onboarding.view.address.var2.AddressFragment">
                <properties>
                    <property name="citiesContainer" value="citiesDc" type="CONTAINER_REF"/> (1)
                    <property name="zipcodePlaceholder" value="Zipcode"/> (2)
                </properties>
            </fragment>
        </details>
    </layout>
</view>| 1 | Передает контейнер данных методу setCitiesContainer(). | 
| 2 | Передает строковый параметр методу setZipcodePlaceholder(). | 
Используйте атрибут value для указания значений и необязательный атрибут type для указания того, что строковое значение должно быть преобразовано одним из подключаемых бинов PropertyParser. Сеттеры должны иметь параметры соответствующих типов.
| Для добавления параметра в Jmix Studio выберите  | 
Если фрагмент создан программным способом, сеттеры могут быть вызваны явно:
@ViewComponent
private CollectionContainer<City> citiesDc;
@Autowired
private Fragments fragments;
@Subscribe
public void onInit(InitEvent event) {
    AddressFragment addressFragment = fragments.create(this, AddressFragment.class);
    addressFragment.setCitiesContainer(citiesDc); (1)
    addressFragment.setZipcodePlaceholder("Zipcode");
    getContent().add(addressFragment);
}| 1 | Перед добавлением в экран в созданный фрагмент передается параметр. | 
Использование компонентов данных
Фрагмент может иметь собственные контейнеры и загрузчики данных, определенные в элементе data XML. В то же время фреймворк создает единственный экземпляр DataContext для экрана и всех его фрагментов. Следовательно, все загруженные сущности объединяются в один контекст, и их изменения сохраняются при сохранении данных включающего экрана.
Следующий пример демонстрирует использование собственных контейнеров данных и загрузчиков во фрагменте.
Предположим, у вас есть сущность City, и вы хотите показать выпадающий список с доступными городами. Вы можете определить компоненты данных в дескрипторе фрагмента так же, как и в обычном экране:
<fragment xmlns="http://jmix.io/schema/flowui/fragment">
    <data>
        <collection id="citiesDc"
                    class="com.company.onboarding.entity.City">
            <fetchPlan extends="_base"/>
            <loader id="citiesDl" readOnly="true">
                <query>
                    <![CDATA[select e from City e]]>
                </query>
            </loader>
        </collection>
    </data>
    <content>
        <formLayout id="addressForm">
            <entityComboBox id="cityField" label="City" itemsContainer="citiesDc"/>
            <textField id="zipcodeField" label="Zipcode"/>
        </formLayout>
    </content>
</fragment>@FragmentDescriptor("address-fragment.xml")
public class AddressFragment extends Fragment<FormLayout> {
    @ViewComponent
    private CollectionLoader<City> citiesDl;
    @Subscribe(target = Target.HOST_CONTROLLER)
    protected void onHostBeforeShow(View.BeforeShowEvent event) { (1)
        citiesDl.load();
    }
}| 1 | Фрагмент подписывается на BeforeShowEventвключающего экрана, поэтому данные фрагмента будут загружены при открытии экрана. | 
Предоставляемые компоненты данных
Следующий пример демонстрирует, как использовать контейнеры данных включающего экрана во фрагменте.
<view xmlns="http://jmix.io/schema/flowui/view">
    <data>
        <instance id="addressDc"
                  class="com.company.onboarding.entity.Address"> (1)
            <fetchPlan extends="_base"/>
            <loader/>
        </instance>
        <collection id="citiesDc"
                    class="com.company.onboarding.entity.City">
            <fetchPlan extends="_base"/>
            <loader id="citiesDl" readOnly="true">
                <query>
                    <![CDATA[select e from City e]]>
                </query>
            </loader>
        </collection>
    </data>
    <facets>
        <dataLoadCoordinator auto="true"/>
    </facets>
    <layout>
        <details id="addressDetails" summaryText="Address" opened="true" alignSelf="STRETCH">
            <fragment class="com.company.onboarding.view.address.var4.AddressFragment"/>
        </details>
    </layout>
</view>| 1 | Контейнер данных, который используется во фрагменте ниже. | 
<fragment xmlns="http://jmix.io/schema/flowui/fragment">
    <data>
        <instance id="addressDc"
                  class="com.company.onboarding.entity.Address"
                  provided="true"/> (1)
        <collection id="citiesDc"
                    class="com.company.onboarding.entity.City"
                    provided="true"/>
    </data>
    <content>
        <formLayout id="addressForm" dataContainer="addressDc">
            <entityComboBox id="cityField" itemsContainer="citiesDc" property="city"/> (2)
            <textField id="zipcodeField" property="zipcode"/>
        </formLayout>
    </content>
</fragment>| 1 | provided="true"означает, что контейнер с тем же идентификатором должен существовать во включающем экране или фрагменте. | 
| 2 | Компонент UI связан с предоставленным контейнером данных. | 
В XML-элементе с атрибутом provided="true" игнорируются все атрибуты, кроме id, однако они могут присутствовать для предоставления информации IDE.
Фрагмент может определять и загрузчики, предоставляемые включающим экраном. Предоставленный загрузчик должен иметь идентификатор, равный идентификатору загрузчика экрана, и атрибут provided="true". Например:
<loader id="addressDl" provided="true"/>