Fragments are reusable UI chunks that don't have their own controller. They're the standard answer to "I need this dialog in five places" and "this toolbar is copy-pasted across views." Used well, they kill duplication across your whole app. Let's cover the three big patterns: dialogs, popovers, and reuse.
Dialogs as fragments
A dialog fragment is an XML file with a Dialog as its root. Load it once in the controller, add it as a dependent of the view (so it inherits models and lifecycle), and open it whenever needed.
// view: my/app/view/fragments/ConfirmDialog.fragment.xml
<core:FragmentDefinition
xmlns:core="sap.ui.core" xmlns="sap.m">
<Dialog title="{i18n>confirmTitle}">
<Text text="{i18n>confirmText}"/>
<beginButton>
<Button text="{i18n>ok}" press=".onConfirmOk"/>
</beginButton>
<endButton>
<Button text="{i18n>cancel}" press=".onConfirmCancel"/>
</endButton>
</Dialog>
</core:FragmentDefinition>
// controller
onOpenConfirm: async function () {
this.oConfirmDialog ??= await Fragment.load({
id: this.getView().getId(),
name: "my.app.view.fragments.ConfirmDialog",
controller: this
});
this.getView().addDependent(this.oConfirmDialog);
this.oConfirmDialog.open();
}
Lazy-loading like this keeps the initial view light, and caching the instance in a field avoids reloading on every click. Remember to destroy it in onExit if the controller can be recreated.
Popovers for contextual actions
Popovers anchor to a control and are perfect for "more info" or quick actions — say you have a list item with a status icon, and tapping it should explain the status without leaving the page.
onStatusPress: async function (oEvent) {
this.oStatusPopover ??= await Fragment.load({
name: "my.app.view.fragments.StatusPopover",
controller: this
});
this.getView().addDependent(this.oStatusPopover);
this.oStatusPopover.openBy(oEvent.getSource());
}
openBy positions the popover relative to the pressed control and handles closing when the user taps elsewhere. Don't build this yourself with absolute positioning — the framework already solved it.
Dialogs block and demand a decision; popovers inform without interrupting. Pick the control that matches the user's intent, not the one that's easiest to code.
Reuse: fragments inside views
Fragments aren't only for popups. Embed a fragment directly in a view to reuse a filter bar, a form section, or a table toolbar across pages.
<Page title="{i18n>orders}">
<subHeader>
<core:Fragment
fragmentName="my.app.view.fragments.FilterBar"
type="XML"/>
</subHeader>
</Page>
Because the fragment shares the view's controller and models, event handlers like press=".onSearch" resolve to the hosting controller automatically. One filter bar fragment, identical behavior on every page.
Fragment best practices
- Prefix IDs: when loading via
Fragment.load, pass the view ID so fragment control IDs stay unique per view instance. - Add as dependent: always
addDependentfor dialogs and popovers, or models and i18n won't resolve inside them. - Keep them dumb: fragments hold layout, not logic. Logic belongs in the hosting controller or a shared helper.
If you're copying XML between views, stop and extract a fragment. It's a five-minute refactor that pays off the first time the design changes.
Which fragment pattern do you use most — dialogs, popovers, or embedded reuse? Let me know in the comments.