<< All versions
Skill v1.0.1
currentAutomated scan100/100javiarmesto/aldc-al-development-collection/skill-pages
+3 new
──Details
PublishedJune 21, 2026 at 09:29 PM
Content Hashsha256:0abf48098df37b4e...
Git SHA981e07514a6d
Bump Typepatch
──Files
Files (1 file, 13.1 KB)
SKILL.md13.1 KBactive
SKILL.md · 436 lines · 13.1 KB
version: "1.0.1" name: skill-pages description: "AL page design patterns for Business Central. Use when creating Card, List, ListPart, Document pages, implementing page extensions, or designing UX layouts."
Skill: AL Page Design
Purpose
Design and customize Business Central pages: Card, List, Document, Worksheet, and RoleCenter page types, page extensions with addafter/addbefore/modify, dynamic UI (visibility, styling), FastTab layout, promoted actions, and FactBoxes.
When to Load
This skill should be loaded when:
- Creating a new page (any type) for a custom or extended table
- Extending a standard BC page with custom fields, groups, or actions
- Designing a Document page with header-lines structure
- Implementing dynamic visibility, conditional styling, or field importance
- Optimizing page performance (FlowField limits, lazy loading)
Core Patterns
Pattern 1: Card Page
Single-record display with FastTab groups:
al
page 50100 "Contoso Project Card"{PageType = Card;SourceTable = "Contoso Project";Caption = 'Project Card';UsageCategory = None; // accessed from list, not searchlayout{area(Content){group(General){Caption = 'General';field("No."; Rec."No."){ApplicationArea = All;Importance = Promoted; // visible in collapsed FastTab}field(Description; Rec.Description){ApplicationArea = All;Importance = Promoted;}field(Status; Rec.Status){ApplicationArea = All;StyleExpr = StatusStyleExpr;}field("Starting Date"; Rec."Starting Date"){ApplicationArea = All;}}group(Details){Caption = 'Details';Visible = DetailsVisible; // dynamic visibilityfield("Project Manager"; Rec."Project Manager"){ApplicationArea = All;}field(Budget; Rec.Budget){ApplicationArea = All;}}}area(FactBoxes){systempart(Notes; Notes) { ApplicationArea = All; }systempart(Links; Links) { ApplicationArea = All; }}}actions{area(Processing){action(Release){ApplicationArea = All;Caption = 'Release';Image = ReleaseDoc;Promoted = true;PromotedCategory = Process;PromotedIsBig = true;trigger OnAction()beginRec.TestField(Status, Rec.Status::Open);Rec.Validate(Status, Rec.Status::Released);Rec.Modify(true);end;}}area(Navigation){action(Entries){ApplicationArea = All;Caption = 'Ledger Entries';Image = LedgerEntries;RunObject = page "Contoso Project Entries";RunPageLink = "Project No." = field("No.");}}}varStatusStyleExpr: Text;DetailsVisible: Boolean;trigger OnAfterGetRecord()beginStatusStyleExpr := GetStatusStyle();DetailsVisible := Rec.Status <> Rec.Status::Open;end;local procedure GetStatusStyle(): Textbegincase Rec.Status ofRec.Status::Open:exit('Standard');Rec.Status::Released:exit('Favorable');Rec.Status::Closed:exit('Subordinate');end;end;}
Pattern 2: List Page
Multi-record display with filters and navigation:
al
page 50101 "Contoso Project List"{PageType = List;SourceTable = "Contoso Project";Caption = 'Projects';UsageCategory = Lists;ApplicationArea = All;CardPageId = "Contoso Project Card";Editable = false;layout{area(Content){repeater(Group){field("No."; Rec."No.") { ApplicationArea = All; }field(Description; Rec.Description) { ApplicationArea = All; }field(Status; Rec.Status){ApplicationArea = All;StyleExpr = StatusStyleExpr;}field("Starting Date"; Rec."Starting Date") { ApplicationArea = All; }// Limit FlowFields on list pages — max 3-4 for performancefield("Total Budget"; Rec."Total Budget") { ApplicationArea = All; }}}}varStatusStyleExpr: Text;trigger OnAfterGetRecord()beginStatusStyleExpr := GetStatusStyle();end;}
List page rules:
- Set
Editable = false— use Card for editing - Set
CardPageIdfor drill-down navigation - Limit FlowFields to 3-4 maximum (each triggers a query per row)
- Use
UsageCategory = Listsfor search/Tell Me discoverability
Pattern 3: Document Page (Header + Lines)
al
page 50102 "Contoso Sales Document"{PageType = Document;SourceTable = "Contoso Document Header";Caption = 'Sales Document';layout{area(Content){group(General){Caption = 'General';field("No."; Rec."No.") { ApplicationArea = All; }field("Customer No."; Rec."Customer No."){ApplicationArea = All;Importance = Promoted;trigger OnValidate()beginCurrPage.Update(); // refresh lines after customer changeend;}field("Document Date"; Rec."Document Date") { ApplicationArea = All; }}part(Lines; "Contoso Document Subpage"){ApplicationArea = All;SubPageLink = "Document No." = field("No.");UpdatePropagation = Both; // sync header ↔ lines}}}}
al
// Lines subpagepage 50103 "Contoso Document Subpage"{PageType = ListPart;SourceTable = "Contoso Document Line";Caption = 'Lines';AutoSplitKey = true; // auto-increment Line No.layout{area(Content){repeater(Lines){field(Type; Rec.Type) { ApplicationArea = All; }field("No."; Rec."No.") { ApplicationArea = All; }field(Description; Rec.Description) { ApplicationArea = All; }field(Quantity; Rec.Quantity) { ApplicationArea = All; }field("Unit Price"; Rec."Unit Price") { ApplicationArea = All; }field("Line Amount"; Rec."Line Amount"){ApplicationArea = All;Editable = false;}}}}}
Pattern 4: Page Extension
Extend standard BC pages without modifying them:
al
pageextension 50100 "Customer Card Ext" extends "Customer Card"{layout{addafter(General){group(ContosoInfo){Caption = 'Contoso Information';field("Contoso Loyalty Points"; Rec."Contoso Loyalty Points"){ApplicationArea = All;ToolTip = 'Total loyalty points for this customer.';}}}modify(Name){// Change properties of existing fieldsStyleExpr = NameStyleExpr;}moveafter("Post Code"; City) // reorder fields}actions{addlast(Processing){action(ContosoCalculatePoints){ApplicationArea = All;Caption = 'Recalculate Points';Image = Calculate;Promoted = true;PromotedCategory = Process;trigger OnAction()varLoyaltyMgt: Codeunit "Contoso Loyalty Management";beginLoyaltyMgt.RecalculatePoints(Rec."No.");CurrPage.Update(false);end;}}}varNameStyleExpr: Text;trigger OnAfterGetRecord()beginNameStyleExpr := GetNameStyle();end;}
Extension placement keywords:
addafter(AnchorField)/addbefore(AnchorField)— position relative to existing fieldaddlast(GroupName)/addfirst(GroupName)— at end/start of groupmodify(FieldName)— change properties of existing fieldmoveafter(Target; FieldToMove)/movebefore(Target; FieldToMove)— reorder
Pattern 5: Field Importance and Promoted Actions
Control visibility and prominence:
al
// Field importance — controls FastTab collapsed behaviorfield(CriticalField; Rec.CriticalField){ApplicationArea = All;Importance = Promoted; // always visible (even when FastTab collapsed)}field(StandardField; Rec.StandardField){ApplicationArea = All;Importance = Standard; // visible when FastTab expanded (default)}field(RareField; Rec.RareField){ApplicationArea = All;Importance = Additional; // hidden unless "Show more" clicked}
al
// Promoted actions — modern actionref syntax (BC 22+)actions{area(Processing){action(Post) { Caption = 'Post'; Image = Post; }action(Release) { Caption = 'Release'; Image = ReleaseDoc; }}area(Promoted){group(Category_Process){Caption = 'Process';actionref(Post_Promoted; Post) { }actionref(Release_Promoted; Release) { }}}}
Workflow
Step 1: Determine Page Type
| Need | PageType | Key Properties | |
|---|---|---|---|
| Single record editing | Card | UsageCategory = None, has Card groups | |
| Multi-record browsing | List | CardPageId, Editable = false, FlowField limits | |
| Header + lines editing | Document | part() with ListPart subpage, UpdatePropagation | |
| Batch data entry | Worksheet | Editable repeater, no Card drill-down | |
| Dashboard/home page | RoleCenter | part() with cues, activities, headlines | |
| Embed in another page | ListPart/CardPart | Used inside part() only |
Step 2: Design Layout
- Group related fields into FastTabs (
group()) - Set
Importance— Promoted for key fields, Additional for rare ones - Add FactBoxes (
area(FactBoxes)) for contextual info - Add Notes and Links system parts
- For Document pages, create the ListPart subpage with
AutoSplitKey
Step 3: Add Actions and Navigation
- Define actions in
area(Processing)andarea(Navigation) - Promote key actions using
area(Promoted)withactionref(BC 22+) - Set appropriate
Imageidentifiers - Add
RunObject/RunPageLinkfor navigation actions
Step 4: Implement Dynamic UI
Visible/Editableexpressions — control field/group visibility based on stateStyleExpr— conditional formatting (Favorable, Unfavorable, Attention, Subordinate, Strong)Enabled— disable actions based on record state- Update expressions in
OnAfterGetRecordtrigger
Step 5: Build and Test
- Build:
al_build - Publish:
al_publish(incremental) - Verify layout, navigation, and field behavior
- Test dynamic visibility and styling with different record states
References
- Page Types — Microsoft Docs
- Page Extension Object
- Actions Overview
- Promoted Actions (actionref)
- Field Importance
- Styling with StyleExpr
Constraints
- This skill covers page design, layout, extensions, and dynamic UI patterns
- Do NOT modify standard BC pages directly — use
pageextensionobjects only - Do NOT place more than 3-4 FlowFields on List pages (performance impact)
- Do NOT skip
ApplicationAreaon any field or action - API page design →
skill-api.md| Performance (FlowFields, SetLoadFields) →skill-performance.md| Page testing →skill-testing.md