Table of Contents

Partial templates

Partial templates provide a powerful way to organize and modularize your UI view and UI component templates. They allow you to break down complex templates into smaller, more manageable pieces while maintaining the full context and scope of the parent (UI view or UI component).

Overview

A partial template is a reusable template fragment that can be defined within a UI view or UI component and referenced from its main template or its other partial templates.

When the application is generated, the <partial-template /> node is replaced by the actual content of the partial template.

Key characteristics:

  • Scoped to the UI view or UI component where they are defined
  • Cannot be shared between multiple UI views or UI components
  • Have access to the same context (properties, actions, methods, computeds, ...) as the main template of the UI view/UI component
  • Can reference other partial templates within the same component
  • Evaluated at generation time, not runtime

Common use cases

Splitting large templates

Break down complex templates into logical sections for better maintainability:

<partial-template name="CustomerHeader" />
<partial-template name="CustomerContactInfo" />
<partial-template name="CustomerOrderHistory" />
<partial-template name="CustomerActions" />

Responsive templates

Create different layouts based on screen size:

<if condition="@Viewport.IsWidthAtLeastMedium">
    <partial-template name="DesktopLayout" />
</if>
<else>
    <partial-template name="MobileLayout" />
</else>

Comparison with UI components

Aspect Partial Templates UI Components
Scope Limited to the parent UI view/UI component Reusable across multiple UI views/components
Context Full access to parent UI view/UI component context The context must explicitly be passed as parameters or accessed via the GetParentViewModel/GetMainViewModel methods
Reusability Cannot be shared Can be used anywhere
Use case Template organization inside a single UI view/UI component Components reusable across the whole application to manage common functionalities available in multiple screens

When to use partial templates

  • Breaking down complex templates
  • Creating conditional (responsive) layouts inside the same UI view/UI component
  • Organizing template code for better readability without introducing new abstraction surface

When to use UI components

  • Reusing functionality or layout across multiple UI views/UI components
  • Encapsulating complex behavior that needs parameters, its own events, or isolated state
  • Sharing a pattern broadly across the cluster (or future clusters) for consistency

Partial template types

A partial template has a type, which defines how it is used:

Type Description
Standard Default type. The partial template is referenced by name with the <partial-template /> node.
SlotContribution The partial template is a contribution to a slot. It is inserted by the slot, never by its own name.

Existing partial templates have no type in their metadata: they are Standard.

Two additional properties are available on a UI view partial template:

Property Type Default value Description
Slot string Name of the slot, in PascalCase. Required for a SlotContribution, forbidden for a Standard partial.
Order integer 0 Display order among the contributions of a slot. Only for a SlotContribution.

Slots

A slot is a named location that a UI view declares in its template with the <partial-template-slot /> node. Other modules complete the UI view by contributing partial templates to this location, without the module declaring the UI view knowing them.

This allows a base module to define a screen that is complete on its own, and sibling modules depending on the base module to add their own content to it.

Key characteristics:

  • Slots are available in UI views only: a <partial-template-slot /> node in a UI component template is a generation error
  • Native Vue views (VuejsComponentContent) do not support slots
  • Inside a context node, a slot belongs to the UI view bound by the context, like a <partial-template /> node
  • A slot without contribution renders nothing
  • Each contribution is validated against its own module
  • A contribution cannot be referenced by a <partial-template /> node: it is only inserted by its slot

Example

The module Dashboard declares a UI view with a Sections slot inside a tabs node:

<tabs>
    <tab-item caption="Overview">
        <text>Overview</text>
    </tab-item>
    <partial-template-slot name="Sections" />
</tabs>

The module Sales, which depends on Dashboard, contributes a tab. The contribution is defined in the metadata of the Sales module (file UIViewPartialTemplates/DashboardUI.yml, named after the UI view):

- Name: SalesSection
  Order: 10
  Slot: Sections
  Template: |-
    <tab-item caption="Sales">
        <text>Sales</text>
    </tab-item>
  Type: SlotContribution

The module Stock, which also depends on Dashboard but not on Sales, contributes another tab in the same way:

- Name: StockSection
  Order: 20
  Slot: Sections
  Template: |-
    <tab-item caption="Stock">
        <text>Stock</text>
    </tab-item>
  Type: SlotContribution

When Sales and Stock are present, the generated UI view displays the tabs Overview, Sales and Stock. When only Dashboard is present, it displays the Overview tab alone.

The root elements of a contribution are inserted where the slot is declared. An element that requires a given parent, like a tab-item in a tabs, is therefore checked against that place when the application is generated. Neos Studio analyzes a contribution alone, so it never reports a missing parent for the root elements of a contribution.

Sorting of the contributions

The contributions to a slot are sorted, whatever the order in which the modules are loaded:

  1. By Order, ascending.
  2. For an equal order, the modules are placed so that a module comes after the modules it depends on. Among the modules whose dependencies are already placed, the smallest module name (ordinal comparison) comes first.
  3. Then by partial template name (ordinal comparison).

A contribution that overrides another one (with OverridenValues) is sorted under the name of its own module.

Errors

The following cases are reported as errors when the application is generated:

  • A contribution targets a slot that no template of the UI view declares.
  • Two different <partial-template-slot /> nodes of the same UI view declare the same slot, even in the two branches of an if/else. A standard partial template that declares a slot can still be used several times: the contributions are written at each use.
  • A slot is declared inside a contribution.
  • A slot is declared inside a repeat node (the only loop component taken into account).
  • A slot is declared in a UI component template.
  • The name of a <partial-template-slot /> node is not in PascalCase.
  • A contribution has no Slot, or the Slot of a contribution is not in PascalCase, or a Standard partial template defines a Slot or an Order.
  • A contribution is referenced by a <partial-template /> node.
  • Two partial templates of a UI view have the same name, unless the second one overrides the first one with OverridenValues.