Fragments
Fragments are reusable UI components defined in XML. They are the primary building blocks of an XWidget application — each fragment describes a piece of your UI that XWidget inflates into Flutter widgets at runtime.
For the attribute value formats accepted by generated inflaters, see Attribute Values.
Defining a Fragment
Create XML files in your fragments directory (default: resources/fragments/):
<!-- resources/fragments/hello_world.xml -->
<Column xmlns="https://xwidget.dev/fragments">
<Text data="Hello World">
<TextStyle for="style" fontWeight="bold" color="#262626"/>
</Text>
<Text>Welcome to XWidget!</Text>
</Column>
Register the directory in pubspec.yaml:
Inflating Fragments in Dart
Use XWidget.inflateFragment() to inflate a fragment into the widget tree:
@override
Widget build(BuildContext context) {
return XWidget.inflateFragment("hello_world", Dependencies());
}
The first argument is the fragment name (without the .xml extension). The second
is the Dependencies instance that provides data for expression evaluation.
Fragment Name Resolution
Fragment names resolve to files in your fragments directory: "settings" finds
settings/index.xml or settings.xml, and subdirectory paths like "auth/login"
use forward slashes. The full resolution rules — and the pubspec.yaml asset
registration every fragment directory needs — live in
Resources.
Query Parameters
You can pass query parameters in the fragment name using standard URL syntax:
Query parameters are parsed and stored as dependencies, making them available to expressions within the fragment.
Nesting Fragments
Use the <fragment> tag to embed one fragment inside another:
<!-- resources/fragments/my_app.xml -->
<MaterialApp xmlns="https://xwidget.dev/fragments">
<Scaffold for="home">
<Column for="body">
<fragment name="header"/>
<fragment name="content"/>
<fragment name="footer"/>
</Column>
</Scaffold>
</MaterialApp>
This lets you decompose complex UIs into smaller, reusable pieces. Each nested fragment is inflated independently and can have its own controller.
Fragment Tag Attributes
| Attribute | Required | Description |
|---|---|---|
name |
Yes | Name of the fragment to render |
for |
No | Named slot in the parent widget to render into |
visible |
No | Controls whether the fragment is rendered (default: true) |
dependenciesScope |
No | How dependencies are passed to the fragment (see below) |
The for Attribute
Use for to render a fragment into a named slot of the parent widget:
The visible Attribute
Conditionally show or hide a fragment:
When visible is false, the fragment is not inflated at all.
Inherited Attributes
Any attributes on the <fragment> tag that are not reserved (name, for,
visible) are forwarded to the child fragment as inherited attributes:
These inherited attributes are available during inflation of the child fragment.
Passing Parameters
Use <param> child elements to pass named parameters to the fragment:
<fragment name="product_card">
<param name="productId" value="${product.id}"/>
<param name="showPrice" value="true"/>
</fragment>
Parameters are added to the fragment's dependencies before inflation.
Navigation
Use XWidget.navigateToFragment() to navigate to a fragment as a new page:
XWidget.navigateToFragment(
'screens/settings',
dependencies,
context: context,
pageName: '/settings',
params: {'userId': currentUser.id},
);
| Parameter | Required | Description |
|---|---|---|
fragmentName |
Yes | Fragment to inflate as the new page |
dependencies |
Yes | Dependency scope for the fragment |
context |
No | Build context for locating the Navigator. If omitted, XWidget uses XRouter.navigatorKey. |
pageName |
No | Route name for RouteSettings (defaults to fragmentName) |
params |
No | Key-value pairs passed to the fragment |
cupertinoStyle |
No | Use iOS-style page transition (default: false) |
removeUntil |
No | RoutePredicate for removing routes beneath the new page |
action |
No | Navigator action to perform (default: NavigatorAction.push) |
The pageName is used by the analytics system for navigation tracking. If you want
analytics to show meaningful page names, set this explicitly.
Dependency Scoping
When a fragment is inflated, you can control how the parent's dependencies are shared
using the dependenciesScope attribute:
| Scope | Behavior |
|---|---|
inherit |
The fragment shares the parent's Dependencies instance (default) |
copy |
The fragment gets a shallow copy — changes don't affect the parent |
new |
The fragment gets a fresh, empty Dependencies instance |
<!-- Children share the parent's dependencies -->
<fragment name="child_fragment" dependenciesScope="inherit"/>
<!-- Children get their own copy -->
<fragment name="child_fragment" dependenciesScope="copy"/>
<!-- Children start with a clean slate -->
<fragment name="child_fragment" dependenciesScope="new"/>
If dependenciesScope is omitted, the default depends on context. If the fragment
has <param> children or query parameters in the name, the scope defaults to copy
to avoid modifying the parent's dependencies. Otherwise, it defaults to inherit.
Variables
Use the <var> tag to set dependency values within a fragment:
The <var> tag supports the spread operator to merge a map into the current
dependencies:
When a parent element contains <var> children and no explicit scope is set,
XWidget automatically uses copy scoping to prevent the variables from leaking
into the parent's dependencies.
XML Caching
XWidget caches parsed XML documents automatically to avoid re-parsing on subsequent
inflations. The cache is managed by the active Resources instance; no configuration
is required.
You rarely need to clear the cache manually — hot reload clears it automatically when a fragment file changes. If you update fragment content through some other mechanism (custom tooling, runtime content injection), clear it explicitly: