Summary
Several MDL properties are typed as an expression but currently take a quoted string, so any single quote inside the expression must be doubled (''). This produces runs of successive quotes that are hard to read, and it signals nothing to the reader/tooling that the value is an expression (it's treated as an opaque string, not syntax-checked).
We should let these properties accept a first-class expression — inner single quotes are literal string delimiters, no escaping — while a quoted '…' continues to work (backward-compatible) and reads as a plain string.
The pain (real examples from the skills/examples today)
-- dynamicclasses: quoted string, single quotes doubled → 5 quotes in a row for an empty else
dynamicclasses: 'if $currentObject/Featured then ''is-featured'' else '''''
-- DynamicCellClass: same
DynamicCellClass: 'if($currentObject/Price > 100) then ''highlight'' else '''' '
The else ''''' (five quotes) is else '' (empty string) inside a doubled-quote string. Easy to get wrong, hard to read.
The language is already inconsistent — first-class forms exist
Some expression contexts already avoid escaping, which proves this is feasible:
- Microflow
if / while / return use the real expression grammar rule (MDLMicroflow.g4): if $x = 'y' then … — single quotes are literal, no doubling.
- Widget
visible: / editable: accept a bracket form (xpathConstraint: LBRACKET xpathExpr RBRACKET, buildConditionalExpression in visitor_page_v3.go): visible: [Name != ''], editable: [CanEdit] — inner quotes literal.
But other expression-typed properties are generic quoted-string properties with no first-class form.
Proposed
Where a property is known to expect an expression, accept a delimited first-class expression (e.g. reuse the [ … ] form that visible:/editable: already use, or the microflow expression grammar) in which single quotes are literal:
-- Proposed — reads cleanly, no escaping:
dynamicclasses: [ if $currentObject/Featured then 'is-featured' else '' ]
DynamicCellClass: [ if $currentObject/Price > 100 then 'highlight' else '' ]
A quoted '…' stays valid and is treated as a plain string literal (backward compatible; existing scripts unchanged).
Expression-typed properties to cover
dynamicclasses: (widget) and DynamicCellClass: (datagrid column)
- Page variable defaults:
variables: { $v: Boolean = <expr> }
- Calculated attributes / calculation expressions
- REST / OData contexts that carry an expression (filter / mapping / condition)
- (Audit for any other property whose value is a Mendix expression)
Benefits
- Readability — no
''''' runs.
- Signals intent + enables checking — a first-class expression can be parsed and syntax/type-checked instead of stored as an opaque string. Directly complements
docs/11-proposals/PROPOSAL_expression_type_checking.md.
- Consistency — one expression story across microflows, visibility, and these properties.
Design questions to nail down in a proposal
- Delimiter: reuse
[ … ] (matches visible:/editable:) vs a distinct delimiter. Note [ … ] today parses xpathExpr (XPath-flavored), whereas dynamicclasses is a full Mendix microflow expression (if … then … else, functions). The microflow expression grammar is the real currency — decide whether the first-class form reuses it.
- Backward compatibility: keep the quoted-string form working everywhere it works today.
- DESCRIBE: emit the first-class form (cleaner round-trip) while still parsing the legacy quoted form.
- Scope: which properties in the first cut (dynamicclasses/DynamicCellClass are the highest-value, most-escaped).
Feasibility
Proven — the mechanism exists (buildConditionalExpression for visible:/editable:; the microflow expression rule). This is an additive grammar/visitor change per property, not a rewrite.
Related
Summary
Several MDL properties are typed as an expression but currently take a quoted string, so any single quote inside the expression must be doubled (
''). This produces runs of successive quotes that are hard to read, and it signals nothing to the reader/tooling that the value is an expression (it's treated as an opaque string, not syntax-checked).We should let these properties accept a first-class expression — inner single quotes are literal string delimiters, no escaping — while a quoted
'…'continues to work (backward-compatible) and reads as a plain string.The pain (real examples from the skills/examples today)
The
else '''''(five quotes) iselse ''(empty string) inside a doubled-quote string. Easy to get wrong, hard to read.The language is already inconsistent — first-class forms exist
Some expression contexts already avoid escaping, which proves this is feasible:
if/while/returnuse the realexpressiongrammar rule (MDLMicroflow.g4):if $x = 'y' then …— single quotes are literal, no doubling.visible:/editable:accept a bracket form (xpathConstraint: LBRACKET xpathExpr RBRACKET,buildConditionalExpressioninvisitor_page_v3.go):visible: [Name != ''],editable: [CanEdit]— inner quotes literal.But other expression-typed properties are generic quoted-string properties with no first-class form.
Proposed
Where a property is known to expect an expression, accept a delimited first-class expression (e.g. reuse the
[ … ]form thatvisible:/editable:already use, or the microflowexpressiongrammar) in which single quotes are literal:A quoted
'…'stays valid and is treated as a plain string literal (backward compatible; existing scripts unchanged).Expression-typed properties to cover
dynamicclasses:(widget) andDynamicCellClass:(datagrid column)variables: { $v: Boolean = <expr> }Benefits
'''''runs.docs/11-proposals/PROPOSAL_expression_type_checking.md.Design questions to nail down in a proposal
[ … ](matchesvisible:/editable:) vs a distinct delimiter. Note[ … ]today parsesxpathExpr(XPath-flavored), whereasdynamicclassesis a full Mendix microflow expression (if … then … else, functions). The microflowexpressiongrammar is the real currency — decide whether the first-class form reuses it.Feasibility
Proven — the mechanism exists (
buildConditionalExpressionforvisible:/editable:; the microflowexpressionrule). This is an additive grammar/visitor change per property, not a rewrite.Related
docs/11-proposals/PROPOSAL_expression_type_checking.md