---
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`
