Sub-views
A sub-view embeds another view (a child grid or form) inside a parent form/view — for example the
line items under an order, or the stock movements under a product. Declare them in <SubConfig> and
place them in the layout with <Sub>.
<SubConfig> <SubView Name="SaleItem" Label="Line Items" Icon="fa fa-list" Type="Table" RenderInView="Expanded" /></SubConfig><SubView>: Name (the child view), Label, Icon, Color, Type (Table/Form),
RenderInView (Disabled/Minimized/Expanded), NameColumn/LabelColumn, FormStyle,
FormStyleColumn, ActivityTypeColumn, CustomJs, InMenu. Reference it from the layout with
<Sub Name="SaleItem" />.
Row button or menu item
Section titled “Row button or menu item”Each sub-view gets an icon button on every grid row by default. A view with many sub-views
ends up with a row of icons that are hard to tell apart. Set InMenu="true" to list the sub-view in
the row’s More (⋮) menu instead, by its Label and Icon. It opens exactly as it does from its
button. Menu sub-views come first in the menu, ahead of Edit, Delete and row actions. When the row has
no other menu items, the menu appears just for them.
<SubConfig> <SubView Type="Table" Name="OrderLines" Label="Lines" Icon="fas fa-list" /> <SubView Type="Table" Name="OrderNotes" Label="Notes" Icon="fas fa-comments" InMenu="true" /></SubConfig>Keep the sub-views people open on most rows as buttons, and move the occasional ones into the menu.
InMenu affects only the grid row. It has no effect on a <Sub> placed in a layout, or on
RenderInView.
In a record view
Section titled “In a record view”A <Sub> in a record’s view mode is read-only. It has no Add New, Edit, Delete, bulk delete or
import. Row actions that run on the server (Sql, Script) are hidden too. Link and Report
actions stay: they only open a URL or a document, so they change nothing. The actions column and its
⋮ menu therefore still appear when a child grid’s rows can only be opened through such a link, for
example a report list with ViewAction="Disabled". To offer the server-run actions, also declare the
child as a <SubView> on the grid row, where it is writable.
For a dynamic workflow task button, NameColumn supplies the form name or route,
LabelColumn supplies its per-row label, FormStyleColumn chooses Modal/Redirected, and
ActivityTypeColumn switches rows whose value is Route from opening a form to navigating:
<SubConfig> <SubView Type="Form" Name="TaskAction" Label="Open Task" Icon="fas fa-play-circle" NameColumn="ActivityRoute" LabelColumn="ActivityTitle" ActivityTypeColumn="ActivityType" FormStyleColumn="ActivityFormStyle" /></SubConfig>Parent key
Section titled “Parent key”When a sub-view loads (grid expand or <Sub> in a form/view), the parent row’s columns are passed to
the child as @Parent__{Column} parameters — notably @Parent__Id (the parent’s primary key). So
the child’s <Sql> filters by, and its <InsertSql> assigns the FK from, @Parent__Id — not the
child’s own column name:
<Sql …> … WHERE si.IsDeleted = 0 AND (@Parent__Id IS NULL OR si.SaleId = @Parent__Id) </Sql><InsertSql> INSERT INTO Sales.SaleItems (SaleId, ProductId, …) VALUES (TRY_CAST(@Parent__Id AS INT), @ProductId, …);</InsertSql>Sub-views vs CartTable
Section titled “Sub-views vs CartTable”For editable line items, prefer a <CartTable> over a standalone
<Sub>. The most direct shape is a view-backed cart —
<CartTable View="OrderLines" ParentKey="OrderId" /> — where this same child view supplies the cart’s
columns and its persistence, and doubles as the read-only View-mode panel (its SubView defaults to
the child view). The cart drives all three modes (editable in Create/Edit, the read-only sub-view in
View), so you never need a separate <Sub>. Use a standalone <Sub> only for child grids that aren’t
backed by a cart.
Worked examples: sample/Inventory/models/views/Products.view.xml (kitchen-sink),
sample/Inventory/models/views/PurchaseOrders.view.xml (sub-views + cart),
sample/Inventory/models/views/PurchaseOrderLines.view.xml (child grid).