Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

CREATE PAGE

Synopsis

CREATE [ OR REPLACE ] PAGE module.Name
(
    [ Params: { $param : Module.Entity | Type [, ...] }, ]
    Title: 'title',
    Layout: Module.LayoutName
    [, Folder: 'path' ]
    [, Variables: { $name : type = 'expression' [, ...] } ]
)
{
    widget_tree
}

Description

Creates a new page in the specified module. A page defines a user interface screen with a title, a layout, optional parameters, and a hierarchical widget tree.

If OR REPLACE is specified and a page with the same qualified name already exists, it is replaced. Otherwise, creating a page with an existing name is an error.

Page Properties

The page declaration block ( ... ) contains comma-separated key-value properties:

  • Params – Page parameters. Each parameter has a $-prefixed name and a type — either an entity (Module.Entity) or a primitive (String, Integer, Decimal, Boolean, DateTime). Parameters are passed when the page is opened (e.g., from a microflow SHOW PAGE or from a data view). Primitive parameters require Mendix 11.6+.
  • Title – The page title displayed in the browser tab or page header.
  • Layout – The layout the page is based on. Must be a qualified name referring to an existing layout (e.g., Atlas_Core.Atlas_Default, Atlas_Core.PopupLayout).
  • Folder – Optional folder path within the module. Nested folders use / separator.
  • Variables – Optional page-level variables with default expressions. Variables can be used for conditional visibility and dynamic behavior.

Widget Tree

The widget tree inside { ... } defines the page content. Widgets are nested hierarchically. Each widget has:

  • A type keyword (e.g., DATAVIEW, TEXTBOX, ACTIONBUTTON)
  • A name (unique within the page, used for ALTER PAGE references)
  • Properties in parentheses (Key: value, ...)
  • Optional children in braces { ... }

Widget Types

Layout Widgets

WidgetDescriptionKey Properties
LAYOUTGRIDResponsive grid containerClass, Style
ROWGrid rowClass
COLUMNGrid columnClass
CONTAINERGeneric div containerClass, Style, DesignProperties
CUSTOMCONTAINERCustom container widgetClass, Style

Data Widgets

WidgetDescriptionKey Properties
DATAVIEWDisplays/edits a single objectDataSource
LISTVIEWRenders a list of objectsDataSource, PageSize
DATAGRIDTabular data display with columnsDataSource, PageSize, Pagination
GALLERYCard-based list displayDataSource, DesktopColumns, TabletColumns, PhoneColumns

Input Widgets

WidgetDescriptionKey Properties
TEXTBOXSingle-line text inputLabel, Attribute
TEXTAREAMulti-line text inputLabel, Attribute
CHECKBOXBoolean toggleLabel, Attribute
RADIOBUTTONSRadio button groupLabel, Attribute
DATEPICKERDate/time selectorLabel, Attribute
COMBOBOXDropdown selectorLabel, Attribute

Display Widgets

WidgetDescriptionKey Properties
DYNAMICTEXTDisplay-only text bound to an attributeAttribute
LABELStudio Pro’s Label widget (Forms$Label): a fixed, translatable caption. describe emits it for existing labels; prefer DYNAMICTEXT for new textContent
IMAGEGeneric imageWidth, Height
STATICIMAGEFixed image from project resourcesWidth, Height
DYNAMICIMAGEImage from an entity attributeWidth, Height

Action Widgets

WidgetDescriptionKey Properties
ACTIONBUTTONButton that triggers an actionCaption, Action, ButtonStyle, Icon
LINKBUTTONHyperlink-styled actionCaption, Action, Icon

Structure Widgets

WidgetDescriptionKey Properties
HEADERPage header area–
FOOTERPage footer area (typically for buttons)–
CONTROLBARControl bar for data grids–
SNIPPETCALLEmbeds a snippetSnippet: Module.SnippetName
NAVIGATIONLISTNavigation sidebar list–

DataSource Types

The DataSource property determines how a data widget obtains its data:

DataSourceSyntaxDescription
ParameterDataSource: $ParamNameBinds to a page parameter or enclosing data view
DatabaseDataSource: DATABASE Module.EntityRetrieves from database
SelectionDataSource: SELECTION widgetNameListens to selection on another widget
MicroflowDataSource: MICROFLOW Module.MFNameCalls a microflow for data

Action Types

The Action property determines what happens when the widget is clicked. It is not a button-only property: a CONTAINER is clickable too and takes the same values, including the argument list.

ActionSyntaxDescription
SaveAction: SAVE_CHANGESCommits and closes
CancelAction: CANCEL_CHANGESRolls back and closes
MicroflowAction: MICROFLOW Module.Name(Param: val)Calls a microflow
NanoflowAction: NANOFLOW Module.Name(Param: val)Calls a nanoflow
PageAction: PAGE Module.PageNameOpens a page
CloseAction: CLOSE_PAGECloses the current page
DeleteAction: DELETEDeletes the context object
NothingAction: NOTHINGDeliberately no action — a decorative button, a card that is not clickable

The set is closed. Anything else in an action slot is an error (MDL-WIDGET28), and that includes a real action keyword missing its argument — Action: OPEN_LINK with no URL, Action: SHOW_PAGE with no page. Such a widget used to be written with no action at all: it rendered, carried its caption, and did nothing, while mxcli check, exec and mxbuild all reported success, because a no-action widget is perfectly legal Mendix. Write NOTHING when a control is genuinely meant to be inert, so that a dead one always means a mistake.

The same values serve OnClick: (an alias of Action:) and OnChange:.

A microflow or nanoflow action is a call: every parameter the flow declares needs an argument, or Mendix rejects the page with CE1571. An enclosing data container of the parameter’s type supplies it without one — but a data grid’s control bar does not, because it is not row-scoped. Pass the grid’s selection there, addressed by the widget’s own name:

DATAGRID dgOrders (DataSource: DATABASE FROM Sales.Order, Selection: Single) {
  COLUMN colNr (Attribute: Number, Caption: 'Order #')
  CONTROLBAR cb {
    CONTAINER cShip (Class: 'command',
      Action: NANOFLOW Sales.ACT_Ship($Order = $dgOrders)) {
      ACTIONBUTTON btnShip (Caption: 'Ship')
    }
  }
}

mxcli check -p <app.mpr> reports a missing argument before mxbuild does.

ButtonStyle Values

Primary, Default, Success, Danger, Warning, Info.

DataGrid Columns

Inside a DATAGRID, child widgets define columns. Each column widget specifies:

PropertyValuesDescription
Attributeattribute nameThe entity attribute to display
CaptionstringColumn header (defaults to attribute name)
Alignmentleft, center, rightText alignment
WrapTexttrue, falseWhether text wraps
Sortabletrue, falseWhether column is sortable
Resizabletrue, falseWhether column is resizable
Draggabletrue, falseWhether column is draggable
Hidableyes, hidden, noColumn visibility control
ColumnWidthautoFill, autoFit, manualWidth mode
Sizeinteger (px)Manual width in pixels
Visibleexpression stringConditional visibility
Tooltiptext stringColumn tooltip

Common Widget Properties

These properties are available on most widget types:

PropertyDescriptionExample
ClassCSS class namesClass: 'card mx-spacing-top-large'
StyleInline CSSStyle: 'padding: 16px;'
DynamicClassesRuntime-computed CSS classes (expression; stacks on Class)DynamicClasses: if $currentObject/IsActive then 'is-active' else ''
EditableEdit controlEditable: NEVER or Editable: ALWAYS
VisibleVisibility expressionVisible: '$showField'
DesignPropertiesAtlas design propertiesDesignProperties: ['Spacing top': 'Large']

Parameters

module.Name
The qualified name of the page (Module.PageName). The module must already exist.
Params: { ... }
Optional page parameters. Each parameter has a $-prefixed name and an entity type.
Title: 'title'
The display title of the page. Required.
Layout: Module.LayoutName
The page layout. Must reference an existing layout. Required.
Folder: 'path'
Optional folder within the module. Nested folders use /.
Variables: { ... }
Optional page variables with type and default expression.

Examples

Edit page with a data view and form fields:

CREATE PAGE MyModule.Customer_Edit
(
    Params: { $Customer: MyModule.Customer },
    Title: 'Edit Customer',
    Layout: Atlas_Core.PopupLayout
)
{
    DATAVIEW dvCustomer (DataSource: $Customer) {
        TEXTBOX txtName (Label: 'Name', Attribute: Name)
        TEXTBOX txtEmail (Label: 'Email', Attribute: Email)
        COMBOBOX cbStatus (Label: 'Status', Attribute: Status)

        FOOTER footer1 {
            ACTIONBUTTON btnSave (Caption: 'Save', Action: SAVE_CHANGES, ButtonStyle: Primary)
            ACTIONBUTTON btnCancel (Caption: 'Cancel', Action: CANCEL_CHANGES)
        }
    }
};

Overview page with a data grid:

CREATE PAGE Sales.Order_Overview
(
    Title: 'Orders',
    Layout: Atlas_Core.Atlas_Default,
    Folder: 'Orders'
)
{
    DATAGRID dgOrders (DataSource: DATABASE Sales.Order, PageSize: 20) {
        COLUMN colId (Attribute: OrderId, Caption: 'Order #')
        COLUMN colDate (Attribute: OrderDate, Caption: 'Date')
        COLUMN colStatus (Attribute: Status, Caption: 'Status')
        COLUMN colAmount (Attribute: TotalAmount, Caption: 'Amount', Alignment: right)
        CONTROLBAR cb1 {
            ACTIONBUTTON btnNew (Caption: 'New Order', Action: SHOW_PAGE Sales.Order_Edit, ButtonStyle: Primary)
        }
    }
};

Page with layout grid and containers:

CREATE PAGE MyModule.Dashboard
(
    Title: 'Dashboard',
    Layout: Atlas_Core.Atlas_Default
)
{
    LAYOUTGRID lgMain {
        ROW row1 {
            COLUMN col1 (Class: 'col-md-8') {
                CONTAINER cntRecent (Class: 'card') {
                    LISTVIEW lvRecent (DataSource: DATABASE MyModule.RecentActivity, PageSize: 5) {
                        DYNAMICTEXT txtDesc (Attribute: Description)
                    }
                }
            }
            COLUMN col2 (Class: 'col-md-4') {
                CONTAINER cntStats (Class: 'card') {
                    DYNAMICTEXT txtCount (Attribute: TotalCount)
                }
            }
        }
    }
};

Page with snippet call:

CREATE PAGE MyModule.Customer_Detail
(
    Params: { $Customer: MyModule.Customer },
    Title: 'Customer Detail',
    Layout: Atlas_Core.Atlas_Default
)
{
    DATAVIEW dvCustomer (DataSource: $Customer) {
        SNIPPETCALL snpHeader (Snippet: MyModule.CustomerHeader)
        TEXTBOX txtName (Label: 'Name', Attribute: Name)
        TEXTBOX txtEmail (Label: 'Email', Attribute: Email)
    }
};

Page with a gallery and selection-driven detail:

CREATE PAGE Sales.Product_Gallery
(
    Title: 'Products',
    Layout: Atlas_Core.Atlas_Default
)
{
    LAYOUTGRID lgMain {
        ROW row1 {
            COLUMN col1 (Class: 'col-md-6') {
                GALLERY galProducts (DataSource: DATABASE Sales.Product, PageSize: 12) {
                    DYNAMICTEXT txtName (Attribute: Name)
                    DYNAMICTEXT txtPrice (Attribute: Price)
                }
            }
            COLUMN col2 (Class: 'col-md-6') {
                DATAVIEW dvDetail (DataSource: SELECTION galProducts) {
                    TEXTBOX txtName (Label: 'Product', Attribute: Name)
                    TEXTBOX txtDesc (Label: 'Description', Attribute: Description)
                }
            }
        }
    }
};

Page with page variables and conditional visibility:

CREATE PAGE MyModule.AdvancedForm
(
    Params: { $Item: MyModule.Item },
    Title: 'Advanced Form',
    Layout: Atlas_Core.Atlas_Default,
    Variables: { $showAdvanced: Boolean = 'false' }
)
{
    DATAVIEW dvItem (DataSource: $Item) {
        TEXTBOX txtName (Label: 'Name', Attribute: Name)
        ACTIONBUTTON btnToggle (Caption: 'Show Advanced', Action: NANOFLOW MyModule.NAV_Toggle)
        CONTAINER cntAdvanced (Visible: '$showAdvanced') {
            TEXTAREA taNotes (Label: 'Notes', Attribute: Notes)
        }
        FOOTER footer1 {
            ACTIONBUTTON btnSave (Caption: 'Save', Action: SAVE_CHANGES, ButtonStyle: Primary)
            ACTIONBUTTON btnCancel (Caption: 'Cancel', Action: CANCEL_CHANGES)
        }
    }
};

Page with microflow data source:

CREATE PAGE Reports.MonthlySummary
(
    Title: 'Monthly Summary',
    Layout: Atlas_Core.Atlas_Default
)
{
    DATAVIEW dvReport (DataSource: MICROFLOW Reports.DS_GetMonthlySummary) {
        DYNAMICTEXT txtPeriod (Attribute: Period)
        DYNAMICTEXT txtRevenue (Attribute: TotalRevenue)
        DYNAMICTEXT txtOrders (Attribute: OrderCount)
    }
};

See Also

CREATE SNIPPET, ALTER PAGE, DROP PAGE, DESCRIBE PAGE, GRANT VIEW ON PAGE