Skip to content

Commit 63b182c

Browse files
akoclaude
andcommitted
docs: add MDL by Example section, show per-attribute javadoc
Add 8 example pages: CRM module, REST integration, data import, master-detail page, ALTER PAGE, validation pattern, security, view entities. Update entity docs to show /** */ on every attribute. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 62196a2 commit 63b182c

File tree

12 files changed

+893
-20
lines changed

12 files changed

+893
-20
lines changed

docs-site/src/SUMMARY.md

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,21 @@
3333

3434
---
3535

36-
# Part II: Migration
36+
# Part II: MDL by Example
37+
38+
- [MDL by Example](examples/README.md)
39+
- [CRM Module](examples/crm-module.md)
40+
- [REST Integration](examples/rest-integration.md)
41+
- [Data Import Pipeline](examples/data-import.md)
42+
- [Master-Detail Page](examples/master-detail.md)
43+
- [Modifying Existing Pages](examples/alter-page.md)
44+
- [Validation Pattern](examples/validation.md)
45+
- [Role-Based Security](examples/security.md)
46+
- [View Entities](examples/view-entities.md)
47+
48+
---
49+
50+
# Part III: Migration
3751

3852
- [Migration Guide](migration/README.md)
3953
- [Assessment](migration/assessment.md)
@@ -44,7 +58,7 @@
4458

4559
---
4660

47-
# Part III: The MDL Language
61+
# Part IV: The MDL Language
4862

4963
- [MDL Basics](language/basics.md)
5064
- [Lexical Structure](language/lexical-structure.md)
@@ -98,7 +112,7 @@
98112

99113
---
100114

101-
# Part IV: Project Tools
115+
# Part V: Project Tools
102116

103117
- [Code Navigation](tools/code-navigation.md)
104118
- [SHOW CALLERS / CALLEES](tools/callers-callees.md)
@@ -143,7 +157,7 @@
143157

144158
---
145159

146-
# Part V: IDE Integration
160+
# Part VI: IDE Integration
147161

148162
- [VS Code Extension](ide/vscode.md)
149163
- [Installation](ide/vscode-installation.md)
@@ -162,7 +176,7 @@
162176

163177
---
164178

165-
# Part VI: Go Library
179+
# Part VII: Go Library
166180

167181
- [Quick Start](library/quickstart.md)
168182
- [Installation](library/installation.md)
@@ -179,7 +193,7 @@
179193

180194
---
181195

182-
# Part VII: MDL Statement Reference
196+
# Part VIII: MDL Statement Reference
183197

184198
- [Connection Statements](reference/connection/README.md)
185199
- [OPEN PROJECT](reference/connection/open-project.md)
@@ -269,7 +283,7 @@
269283

270284
---
271285

272-
# Part VIII: Architecture & Internals
286+
# Part IX: Architecture & Internals
273287

274288
- [System Architecture](internals/architecture.md)
275289
- [Layer Diagram](internals/layers.md)
@@ -291,7 +305,7 @@
291305

292306
---
293307

294-
# Part IX: Appendixes
308+
# Part X: Appendixes
295309

296310
- [MDL Quick Reference](appendixes/quick-reference.md)
297311
- [Data Type Mapping Table](appendixes/data-type-mapping.md)

docs-site/src/examples/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# MDL by Example
2+
3+
This part presents complete, self-contained MDL examples that show how the language comes together for real use cases. Each example is ready to run against a Mendix project.
4+
5+
Where Part III covers MDL syntax one statement at a time, these examples show full features built end to end -- domain model, business logic, pages, and security working together.
6+
7+
## Examples
8+
9+
| Example | What It Shows |
10+
|---------|---------------|
11+
| [CRM Module](crm-module.md) | Full CRUD feature: entities with documented attributes, associations, validation microflow, overview and edit pages, security |
12+
| [REST Integration](rest-integration.md) | Call external APIs from microflows: GET/POST, headers, authentication, error handling, JSON responses |
13+
| [Data Import Pipeline](data-import.md) | Connect to an external database, explore schema, import data with association linking, generate connectors |
14+
| [Master-Detail Page](master-detail.md) | Gallery with selection binding, detail form, save/cancel actions |
15+
| [Modifying Existing Pages](alter-page.md) | ALTER PAGE to add fields, change buttons, replace sections, drop widgets |
16+
| [Validation Pattern](validation.md) | Two-microflow validation with field-level feedback |
17+
| [Role-Based Security](security.md) | Module roles, user roles, entity access with XPath row-level constraints, demo users |
18+
| [View Entities](view-entities.md) | OQL-backed aggregation with JOIN, filtered retrieval in microflows |
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Modifying Existing Pages
2+
3+
`ALTER PAGE` modifies widgets in place without recreating the entire page. This is useful for incremental changes, maintenance, and agent-driven iteration.
4+
5+
## Change a Button
6+
7+
```sql
8+
ALTER PAGE CRM.Customer_Edit {
9+
SET (Caption = 'Save & Close', ButtonStyle = Success) ON btnSave
10+
};
11+
```
12+
13+
## Add a Field After an Existing One
14+
15+
```sql
16+
ALTER PAGE CRM.Customer_Edit {
17+
INSERT AFTER txtEmail {
18+
TEXTBOX txtPhone (Label: 'Phone', Attribute: Phone)
19+
}
20+
};
21+
```
22+
23+
## Remove Widgets
24+
25+
```sql
26+
ALTER PAGE CRM.Customer_Edit {
27+
DROP WIDGET txtLegacyField, lblOldNote
28+
};
29+
```
30+
31+
## Replace an Entire Footer
32+
33+
```sql
34+
ALTER PAGE CRM.Customer_Edit {
35+
REPLACE footer1 WITH {
36+
FOOTER newFooter {
37+
ACTIONBUTTON btnSave (Caption: 'Save', Action: SAVE_CHANGES, ButtonStyle: Success)
38+
ACTIONBUTTON btnDelete (Caption: 'Delete', Action: DELETE, ButtonStyle: Danger)
39+
ACTIONBUTTON btnCancel (Caption: 'Cancel', Action: CANCEL_CHANGES)
40+
}
41+
}
42+
};
43+
```
44+
45+
## Multiple Changes at Once
46+
47+
```sql
48+
ALTER PAGE CRM.Customer_Edit {
49+
SET Title = 'Edit Customer Details';
50+
SET Label = 'Email Address' ON txtEmail;
51+
INSERT AFTER txtPhone {
52+
TEXTBOX txtWebsite (Label: 'Website', Attribute: Website)
53+
};
54+
DROP WIDGET lblInternalRef
55+
};
56+
```
57+
58+
## Add a Page Variable
59+
60+
```sql
61+
ALTER PAGE CRM.ProductOverview {
62+
ADD Variables $showStockColumn: Boolean = 'if (3 < 4) then true else false'
63+
};
64+
```
65+
66+
## Works on Snippets Too
67+
68+
```sql
69+
ALTER SNIPPET CRM.NavigationMenu {
70+
SET Caption = 'Dashboard' ON btnHome;
71+
INSERT AFTER btnHome {
72+
ACTIONBUTTON btnReports (
73+
Caption: 'Reports',
74+
Action: SHOW_PAGE CRM.Reports_Overview
75+
)
76+
}
77+
};
78+
```
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
# CRM Module
2+
3+
A complete customer management feature: domain model, validation, CRUD pages, and security -- all in one script.
4+
5+
## Domain Model
6+
7+
```sql
8+
-- Enumerations first (referenced by entities)
9+
CREATE ENUMERATION CRM.CustomerStatus (
10+
Active 'Active',
11+
Inactive 'Inactive',
12+
Suspended 'Suspended'
13+
);
14+
15+
CREATE ENUMERATION CRM.ContactType (
16+
Email 'Email',
17+
Phone 'Phone',
18+
Visit 'Visit'
19+
);
20+
21+
-- Entities with per-attribute documentation
22+
/** Customer master data */
23+
@Position(100, 100)
24+
CREATE PERSISTENT ENTITY CRM.Customer (
25+
/** Auto-generated unique identifier */
26+
CustomerId: AutoNumber NOT NULL UNIQUE DEFAULT 1,
27+
/** Full legal name */
28+
Name: String(200) NOT NULL ERROR 'Customer name is required',
29+
/** Primary contact email */
30+
Email: String(200) UNIQUE ERROR 'Email already exists',
31+
/** Phone number in international format */
32+
Phone: String(50),
33+
/** Current account balance */
34+
Balance: Decimal DEFAULT 0,
35+
/** Whether the account is active */
36+
IsActive: Boolean DEFAULT TRUE,
37+
/** Current lifecycle status */
38+
Status: Enumeration(CRM.CustomerStatus) DEFAULT 'Active',
39+
/** Free-form notes about this customer */
40+
Notes: String(unlimited)
41+
)
42+
INDEX (Name)
43+
INDEX (Email);
44+
/
45+
46+
/** Record of a customer interaction */
47+
@Position(400, 100)
48+
CREATE PERSISTENT ENTITY CRM.ContactLog (
49+
/** Date and time of the interaction */
50+
ContactDate: DateTime NOT NULL,
51+
/** Type of interaction */
52+
Type: Enumeration(CRM.ContactType) DEFAULT 'Email',
53+
/** Summary of what was discussed */
54+
Summary: String(2000) NOT NULL ERROR 'Summary is required',
55+
/** Follow-up needed? */
56+
FollowUpRequired: Boolean DEFAULT FALSE
57+
);
58+
/
59+
60+
-- Associations
61+
CREATE ASSOCIATION CRM.ContactLog_Customer
62+
FROM CRM.Customer TO CRM.ContactLog
63+
TYPE Reference OWNER Default;
64+
/
65+
```
66+
67+
## Validation Microflow
68+
69+
The two-microflow pattern: a validation microflow returns field-level feedback, and an action microflow calls it before saving.
70+
71+
```sql
72+
CREATE MICROFLOW CRM.VAL_Customer ($Customer: CRM.Customer)
73+
RETURNS Boolean AS $IsValid
74+
BEGIN
75+
DECLARE $IsValid Boolean = true;
76+
77+
IF trim($Customer/Name) = '' THEN
78+
SET $IsValid = false;
79+
VALIDATION FEEDBACK $Customer/Name MESSAGE 'Name cannot be empty';
80+
END IF;
81+
82+
IF $Customer/Email != empty AND NOT contains($Customer/Email, '@') THEN
83+
SET $IsValid = false;
84+
VALIDATION FEEDBACK $Customer/Email MESSAGE 'Enter a valid email address';
85+
END IF;
86+
87+
IF $Customer/Balance < 0 THEN
88+
SET $IsValid = false;
89+
VALIDATION FEEDBACK $Customer/Balance MESSAGE 'Balance cannot be negative';
90+
END IF;
91+
92+
RETURN $IsValid;
93+
END;
94+
/
95+
96+
CREATE MICROFLOW CRM.ACT_Customer_Save ($Customer: CRM.Customer)
97+
RETURNS Boolean AS $IsValid
98+
BEGIN
99+
$IsValid = CALL MICROFLOW CRM.VAL_Customer($param = $Customer);
100+
101+
IF $IsValid THEN
102+
COMMIT $Customer;
103+
CLOSE PAGE;
104+
END IF;
105+
106+
RETURN $IsValid;
107+
END;
108+
/
109+
```
110+
111+
## Pages
112+
113+
```sql
114+
-- Overview page with data grid
115+
CREATE PAGE CRM.Customer_Overview (
116+
Title: 'Customers',
117+
Layout: Atlas_Core.Atlas_Default
118+
) {
119+
DATAGRID2 ON CRM.Customer (
120+
COLUMN Name { Caption: 'Name' }
121+
COLUMN Email { Caption: 'Email' }
122+
COLUMN Phone { Caption: 'Phone' }
123+
COLUMN Status { Caption: 'Status' }
124+
COLUMN IsActive { Caption: 'Active' }
125+
SEARCH ON Name, Email
126+
BUTTON 'New' CALL CRM.Customer_NewEdit
127+
BUTTON 'Edit' CALL CRM.Customer_NewEdit
128+
BUTTON 'Delete' CALL CONFIRM DELETE
129+
)
130+
};
131+
/
132+
133+
-- NewEdit page with validation
134+
CREATE PAGE CRM.Customer_NewEdit (
135+
Params: { $Customer: CRM.Customer },
136+
Title: 'Customer',
137+
Layout: Atlas_Core.PopupLayout
138+
) {
139+
LAYOUTGRID mainGrid {
140+
ROW row1 {
141+
COLUMN col1 (DesktopWidth: AutoFill) {
142+
DATAVIEW dataView1 (DataSource: $Customer) {
143+
TEXTBOX txtName (Label: 'Name', Attribute: Name)
144+
TEXTBOX txtEmail (Label: 'Email', Attribute: Email)
145+
TEXTBOX txtPhone (Label: 'Phone', Attribute: Phone)
146+
TEXTAREA txtNotes (Label: 'Notes', Attribute: Notes)
147+
FOOTER footer1 {
148+
ACTIONBUTTON btnSave (
149+
Caption: 'Save',
150+
Action: CALL CRM.ACT_Customer_Save,
151+
ButtonStyle: Success
152+
)
153+
ACTIONBUTTON btnCancel (Caption: 'Cancel', Action: CANCEL_CHANGES)
154+
}
155+
}
156+
}
157+
}
158+
}
159+
};
160+
/
161+
```
162+
163+
## Security
164+
165+
```sql
166+
-- Module roles
167+
CREATE MODULE ROLE CRM.User;
168+
CREATE MODULE ROLE CRM.Admin DESCRIPTION 'Full customer management access';
169+
170+
-- Entity access
171+
GRANT CRM.Admin ON CRM.Customer (CREATE, DELETE, READ *, WRITE *);
172+
GRANT CRM.User ON CRM.Customer (CREATE, READ *, WRITE *)
173+
WHERE '[IsActive = true]';
174+
175+
GRANT CRM.Admin ON CRM.ContactLog (CREATE, DELETE, READ *, WRITE *);
176+
GRANT CRM.User ON CRM.ContactLog (CREATE, READ *, WRITE *);
177+
178+
-- Document access
179+
GRANT EXECUTE ON MICROFLOW CRM.ACT_Customer_Save TO CRM.User;
180+
GRANT VIEW ON PAGE CRM.Customer_Overview TO CRM.User;
181+
GRANT VIEW ON PAGE CRM.Customer_NewEdit TO CRM.User;
182+
183+
-- User roles
184+
CREATE OR MODIFY USER ROLE CRMUser (System.User, CRM.User);
185+
CREATE OR MODIFY USER ROLE CRMAdmin (System.User, CRM.Admin);
186+
187+
-- Demo users for testing
188+
CREATE OR MODIFY DEMO USER 'crm_user' PASSWORD 'Password1!' (CRMUser);
189+
CREATE OR MODIFY DEMO USER 'crm_admin' PASSWORD 'Password1!' (CRMAdmin);
190+
ALTER PROJECT SECURITY DEMO USERS ON;
191+
```

0 commit comments

Comments
 (0)