fragments · git:20260821.ff81a24 · 2026-08-21 · sha256 1d862fb57b7f512c
fragments git:20260821.ff81a24A
Immutable. This exact content is served forever at /api/v1/blob/1d862fb57b7f512c.
---
name: fragments
description: "Define reusable widget groups with DEFINE FRAGMENT and place them with USE FRAGMENT. Use when the same widget pattern repeats across pages and should be written once."
---
# Mendix Fragments Skill
## When to Use This Skill
Use this skill when:
- Defining reusable widget groups with `define fragment`
- Inserting fragments into pages or snippets with `use fragment`
- Listing or inspecting fragments with `show fragments` / `describe fragment`
- Building multiple pages that share common widget patterns (footers, form fields, buttons)
- Avoiding copy-paste of repeated widget structures across pages
## What Are Fragments?
Fragments are **script-scoped, transient** widget groups:
- Defined once, reused in multiple pages/snippets within the same script
- **Not persisted** in the MPR file — they exist only during script execution
- Widgets are deep-cloned on expansion (each USE gets independent copies)
- Optional prefix support to avoid name conflicts when using the same fragment multiple times
## Syntax Reference
### DEFINE FRAGMENT
```mdl
define fragment SaveCancelFooter as {
footer footer1 {
actionbutton btnSave (caption: 'Save', action: save_changes, buttonstyle: primary)
actionbutton btnCancel (caption: 'Cancel', action: cancel_changes)
}
};
```
Multiple top-level widgets:
```mdl
define fragment CustomerFields as {
textbox txtName (label: 'Name', attribute: Name)
textbox txtEmail (label: 'Email', attribute: Email)
textbox txtPhone (label: 'Phone', attribute: Phone)
};
```
### USE FRAGMENT
Inside a page or snippet body:
```mdl
create page Module.CustomerEdit
(
params: { $Customer: Module.Customer },
title: 'Edit Customer',
layout: Atlas_Core.PopupLayout
)
{
dataview dvCustomer (datasource: $Customer) {
use fragment CustomerFields
use fragment SaveCancelFooter
}
};
```
With prefix (avoids name conflicts):
```mdl
use fragment SaveCancelFooter as order_
-- Creates: order_footer1, order_btnSave, order_btnCancel
```
### Content Slots — wrap arbitrary content
A plain fragment substitutes a **fixed** widget group. A **content slot** lets a
fragment **wrap arbitrary caller-supplied content** — a reusable shell (a card,
panel, or section) whose body varies per use. Declare a `slot` where the caller's
widgets should land, then fill it with the `use fragment X { … }` payload form:
```mdl
define fragment Card as {
container cardWrap (class: 'card', designproperties: ['Card style': on]) {
container cardBody (class: 'card-body') {
slot content -- caller's widgets are spliced in here
}
}
};
create page Module.Dashboard (title: 'Dashboard', layout: Atlas_Core.Atlas_Default) {
use fragment Card {
dynamictext cardHeading (content: 'Welcome', rendermode: H2)
dynamictext cardText (content: 'Any widgets can go inside the reusable Card shell')
}
};
```
Rules (v1):
- The slot name is optional and defaults to `content`; a fragment supports one slot.
- Using a slotted fragment with **no** payload (`use fragment Card`) expands the
slot to nothing — a valid empty shell.
- Supplying a payload to a fragment that declares **no** slot is an error.
- The payload is deep-cloned; `as prefix_` still renames the fragment's own
widgets (not the caller's payload).
- The slot resolves at expansion — `describe page` shows the fully-expanded tree
(no slot marker), and there are no BSON/round-trip surprises.
> For varying a leaf **value** (a label or attribute name) rather than wrapping a
> subtree, scalar params (`define fragment F($label, $attr) as …`) are a planned
> v1.1 follow-up; today use a slot plus a one-line value fill.
### Parameter bindings — datasource & action (experimental)
The content slot varies *structure* (which widgets). Typed **parameters** vary
*data* and *behavior*: a fragment can declare a `datasource` and/or an `action`
parameter, reference it with `$name` in a datasource/action position, and receive
its value at the use site. This turns a shell into a real reusable component —
one panel bound to a different entity and a different handler per use.
```mdl
define fragment DataPanel($data: datasource, $onEdit: action) as {
container panelWrap (class: 'card') {
listview lvItems (datasource: $data) {
slot content
actionbutton btnEdit (caption: 'Edit', action: $onEdit, buttonstyle: primary)
}
}
};
create page Module.Orders (title: 'Orders', layout: Atlas_Core.Atlas_Default) {
use fragment DataPanel ($data: database Module.Order, $onEdit: microflow Module.EditOrder) {
dynamictext panelHeading (content: 'Orders', rendermode: H4)
}
};
```
Rules:
- Param kinds are `datasource` (`$var` / `database E` / `$currentObject/Assoc` / `microflow M`) and `action` (a microflow / nanoflow / `save_changes` / `show_page` / …).
- Every declared parameter must be supplied; unknown args and type mismatches are errors.
- Values substitute at expansion — `describe page` shows the concrete datasource/action, no `$param`.
**Building blocks** can't declare params (they're authored in Studio Pro), but a
`use building block` accepts **rebind overrides** that rewrite the block's
outermost datasource and/or its first button after the copy:
```mdl
use building block Atlas_Web_Content.List_Cards
(datasource: database Module.Order, action: microflow Module.OpenOrder) as orders_;
```
Binding-point rule (prototype): datasource → the first widget carrying a
datasource; action → the first button widget. For anything more specific, copy
the block in with `as prefix_` and use `alter page … set … on prefix_widget`.
### SHOW FRAGMENTS
```mdl
show fragments;
-- Lists all defined fragments with widget counts
```
### DESCRIBE FRAGMENT
```mdl
describe fragment SaveCancelFooter;
-- Outputs the full MDL definition
```
## Common Patterns
### Pattern 1: Standard CRUD Footer
```mdl
define fragment CrudFooter as {
footer footer1 {
actionbutton btnSave (caption: 'Save', action: save_changes, buttonstyle: primary)
actionbutton btnCancel (caption: 'Cancel', action: cancel_changes)
}
};
-- Use in every edit page
create page Module.Customer_Edit (...) {
dataview dv (datasource: $Customer) {
textbox txtName (label: 'Name', attribute: Name)
use fragment CrudFooter
}
};
create page Module.Order_Edit (...) {
dataview dv (datasource: $Order) {
textbox txtNumber (label: 'Order #', attribute: Number)
use fragment CrudFooter
}
};
```
### Pattern 2: Form Field Groups
```mdl
define fragment AddressFields as {
textbox txtStreet (label: 'Street', attribute: Street)
textbox txtCity (label: 'City', attribute: City)
textbox txtZip (label: 'Zip Code', attribute: ZipCode)
textbox txtCountry (label: 'Country', attribute: Country)
};
-- Reuse in customer and supplier pages
create page Module.Customer_Edit (...) {
dataview dv (datasource: $Customer) {
textbox txtName (label: 'Name', attribute: Name)
use fragment AddressFields
use fragment CrudFooter
}
};
```
### Pattern 3: Same Fragment with Prefix
```mdl
define fragment ActionButtons as {
actionbutton btnApprove (caption: 'Approve', action: save_changes, buttonstyle: success)
actionbutton btnReject (caption: 'Reject', action: cancel_changes, buttonstyle: danger)
};
create page Module.DualPanel (...) {
layoutgrid lg {
row row1 {
column col1 (desktopwidth: 6) {
use fragment ActionButtons as left_
}
column col2 (desktopwidth: 6) {
use fragment ActionButtons as right_
}
}
}
};
```
## Common Mistakes
### Duplicate Fragment Names
```mdl
-- WRONG: Defining the same fragment name twice causes an error
define fragment footer as { ... };
define fragment footer as { ... }; -- Error: fragment "Footer" already defined
```
### Missing Fragment
```mdl
-- WRONG: Using a fragment that hasn't been defined
create page Module.MyPage (...) {
use fragment NonExistent -- Error: fragment "NonExistent" not found
};
```
### Name Conflicts Without Prefix
```mdl
-- WRONG: Using same fragment twice without prefix creates duplicate widget names
use fragment footer
use fragment footer -- Widget name "footer1" already exists!
-- CORRECT: Use prefix for uniqueness
use fragment footer as first_
use fragment footer as second_
```
### Fragment Order
```mdl
-- WRONG: Using a fragment before defining it
create page Module.MyPage (...) {
use fragment footer -- Error: fragment "Footer" not found
};
define fragment footer as { ... };
-- CORRECT: Define before use
define fragment footer as { ... };
create page Module.MyPage (...) {
use fragment footer -- OK
};
```
## Validation Checklist
- [ ] All `define fragment` statements appear before their `use fragment` references
- [ ] No duplicate fragment names in the script
- [ ] Prefix used when the same fragment appears multiple times on one page
- [ ] Fragment widget names don't conflict with other widgets on the page
- [ ] All widgets inside fragments use valid syntax (same as page bodies)
- [ ] A `use fragment X { … }` payload is only supplied when fragment `X` declares a `slot`
- [ ] A slotted fragment has exactly one `slot` (v1 supports a single slot)
## Related Documentation
- `mxcli syntax fragment` — CLI help topic
- `create-page` — Page/widget syntax reference
- `overview-pages` — CRUD page patterns
- Proposal: `docs/11-proposals/proposal_page_composition.md`