Facets in Fragments
Fragments support the same facet mechanism as views. You can use framework-provided facets inside fragments to add reusable functionality. For a general introduction to facets, see Facets.
The following facets are available for use in fragments:
-
timer– creates a client-side timer that can trigger periodic actions. -
fragmentSettings– saves UI component settings for a specific user. -
fragmentDataLoadCoordinator– controls how data is loaded into the fragment. -
urlQueryParameters– persists the state of UI components in the URL.
For example:
<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>
|
Some facets require the fragment to have an ID. You can set it either in XML using the settings-fragment-view.xml
The same fragment can be created programmatically using the SettingsFragmentView.java
|
Timer Facet
The timer facet creates a client-side timer element. It uses the same implementation as the view-level timer, so all properties and events work the same in fragments.
Fragment XML example:
<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>
Fragment controller example:
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 Facet
The fragmentSettings facet saves settings for visual components. Saving occurs when the view is closed, similar to the setting facet for views.
A fragment using fragmentSettings must have an ID. You can set it in XML or programmatically.
|
Key differences from view settings:
-
Settings are applied at the
HostView.ReadyEventevent in the fragment lifecycle (instead ofReadyEventfor views). -
This ensures settings are applied at the latest possible moment in both view and fragment lifecycles.
-
Each fragment on a view stores its own separate set of settings.
-
A dedicated XML tag
fragmentSettingsis used.
Fragment XML example:
<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>
Fragment controller example:
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 Facet
The fragmentDataLoadCoordinator facet controls data loading within a fragment. For example, you can set a loading trigger on specific fragment lifecycle events.
Available lifecycle events for fragments:
-
Fragment.ReadyEvent -
HostView.InitEvent -
HostView.BeforeShowEvent -
HostView.ReadyEvent
The rest of the functionality works the same as the dataLoadCoordinator facet for views.
Fragment XML example:
<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>
Fragment controller example:
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 Facet
The urlQueryParameters facet persists component state in the URL. This is useful when using the URL-first approach – leaving and returning to a view preserves information like filter states.
| The fragment must have an ID, as its value is used for serialization. You can set the ID in XML or programmatically. |
The working principle is similar to the urlQueryParameters facet for views.
Fragment XML example:
<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>
Fragment controller example:
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> {
}