Repository navigation
Sync ako/mxcli: page properties on Mendix 9.x/10.x, workflow button actions, pluggable widget events; recovering old-mxcli merge bases - #1671
Merged
Conversation
…ets) `mxcli fix property-sets`, like any Studio Pro save, completes property names only from its own commit on. A merge or rebase whose merge base is an earlier revision written by mxcli before 0.26 still throws "Objects with ID … do not have the same properties" on every document that was incomplete there and that both branches changed. A customer on 11.12.2 hit this during a rebase and could not reopen the project, because Studio Pro re-runs the unfinished merge on open. The user manual (Working Outside Studio Pro) and the command's help now say that the repair only works forward, that it should run once on the main branch, and how to get past a stuck merge: abort it; find the units with --dry-run on the merge base; put the ones both branches changed back to the merge base on your branch (with fix hashes --repair for the .mpr index); merge rather than rebase; redo the edits. They also warn against re-creating an entity, attribute or association, whose new GUID costs its data. Measured with `mx merge` (Studio Pro's merge engine) on 11.13.0, using testdata/pedapp and an access rule written by a v0.25.0 build: - before the steps, exit 129 with the customer's exception - with the repaired side against the old base, also exit 129 - after the steps, exit 0; the merged project keeps both branches' other edits, and `mx check` matches the untouched fixture Taking one side of the conflicted files at the git level does not work in general: the v2 .mpr indexes every unit and conflicts too. Records the diagnosis as a finding (refs mendixlabs#1373, #1097). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82tNcDLefAskVSzcKPm
"When a native child widget is rebuilt, its KeyboardType and Placeholder are lost, for example on text boxes in the native snippets." Forms$TextBox.KeyboardType is the keyboard a native app opens for the box. Its members are Default, NumberPad, DecimalPad, EmailAddress, PhonePad and URL (mendixmodelsdk, declared from 8.0). It had no MDL spelling: describe printed nothing and the writer wrote "Default". So a rewrite reset every native text box's keyboard, on every version. Now `textbox t (Attribute: Email, KeyboardType: EmailAddress)`: - Members are matched case-insensitively and stored as Mendix spells them. - Describe omits Default. - An unknown member is refused by exec, and by check as MDL-WIDGET18. - The key is a text box's only. It is exempted per type, like the submit keys, so it still warns on any other widget. The placeholder half of the report is a version-shape gap, fixed in the next commit. Verified: builder, writer-facing model, describe and check tests, each red before the change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82sUVQEB3K5W5vh85wM
"describe drops widgets' design properties on 9.24, so a describe → exec
round trip removes them". Rebuilt text boxes lost their placeholder too.
Five page properties kept their meaning and changed storage shape at a
version. mxcli read and wrote only the newer shape. Measured on the
pages of a Studio Pro-authored 9.24.30 app and in mendixmodelsdk:
| Property | Older shape | Until |
|------------------------------|--------------------------------------|-------|
| design property | Type/StringValue/BooleanValue flat | 10.2 |
| data view source parameter | PageParameter/SnippetParameter names | 10.0 |
| data view editability | Editable bool | 10.7 |
| text box/area/date placeholder | Placeholder Texts$Text | 10.11 |
| data source ForceFullObjects | not stored | 10.8 |
The effects on 9.24:
- describe printed none of these, so a round trip removed them. On
Home_Web it printed "Replaced page" and changed the bytes.
- Any page with a data view or a design property was refused at
write.
- The placeholder, the data view source's parameter and
ForceFullObjects are declared on abstract supertypes. The property
floor cannot see those, so the newer key passed unrefused and the
older key was never written. The data view source showed up as
CE6050.
- alter styling on a stored 9.x entry reported "Updated styling" and
changed nothing. It updated through DSet("Value"), which does nothing
when the key is missing.
The fix:
- canon.LowerToProjectShape runs in normalizePropertySetsFor, the hook
every unit write passes, before the floor and before Reconcile. It
rewrites the current shape into the project's, so every writer is
covered, ALTER and pluggable templates included. A lowered rewrite of
a stored unit still elides.
- What the older shape cannot hold is refused, naming the widget:
- Spacing, colour or toggle-group design properties;
- conditional editability;
- placeholder parameters;
- a data view fed by another widget.
- describe reads both shapes.
- The mutator rebuilds the entry it sets, keeping its $ID.
Measured on fresh 9.24.30 apps (mxbuild 9.24.30.51827):
- bug-test 1209-mendix9-page-shapes.mdl: mx check 0 errors, the same as
the blank app. main stops on KeyboardType; without it, main refuses
the page for Editability and DesignPropertyValue.Value.
- describe → exec of Studio Pro's Home_Web: "Unchanged page", bytes
identical. On main: "Replaced page", design properties removed.
- describe → exec of the new page: "Unchanged page", bytes identical.
- alter styling on Home_Web's text2 stores "Header color". On main the
entry stays "Detail color".
- Doctype gate on 9.24: 12-styling passes. 15-fragment's data views
write, then stop on CE0560. 29-datagrid stops on
MicroflowParameterMapping.Expression. Both of those are other #1163
rows.
- On 10.24 and 11.13, where nothing is lowered, 03-page, 12-styling,
15-fragment and 29-datagrid pass.
Tests (each red first): writer_version_shape_test.go, covering 9.24,
the boundaries either side of 10.2/10.7/10.11, the refusals and an 11.13
control; cmd_pages_describe_mendix9_shapes_1209_test.go, with a
10.11-shape control; TestSetDesignProperty_OverwritesAMendix9Entry.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011oK82sUVQEB3K5W5vh85wM
Two fixes in a row (#1754, #1209) had the same shape: one fact stored differently below a version. The floor sees keys, not facts, and misses supertype-declared ones. The page now says where the cover-all remedy sits (canon.LowerToProjectShape), and where to get the older shape's real bytes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82sUVQEB3K5W5vh85wM
…#832) Symptom: with the pluggable patch from df82f53 in place, re-running `describe page WorkflowCommons.TaskInbox` unchanged on ako/TestApp (11.15.0-rc.4) still reported "Replaced page" and left 4 Forms$OpenUserTaskClientAction where there had been 6: the link button in the last column of the "My open tasks" and "All open tasks" grids, which opens the task, became a Forms$NoAction. TaskDashboard lost the same two. check, exec and mx check were all clean. Cause: describe had no case for Forms$OpenUserTaskClientAction ("Show user task page"), Forms$OpenWorkflowClientAction ("Show workflow admin page") or Forms$CallWorkflowClientAction ("Call workflow"), so it printed no Action, and a classic widget is rebuilt from the statement: no Action builds a NoAction. The grids' own row click survived only because the patch keeps a property both builds agree on; a column's content always takes the statement's build. `complete task` also rebuilt ClosePage and Commit as true whatever was stored, and describe printed neither. Fix: spell them in the words the microflow actions use, with their settings in `with ( … )`: open user task [with (AssignOnOpen: false, OpenWhenAssigned: true)] open workflow with (DefaultPage: Module.Page) call workflow Module.WF [with (ClosePage: false, Confirmation: '…')] complete task 'X' [with (ClosePage: false, Commit: false)] describe prints each, and only the settings that differ from a new action (the Model SDK's constructor defaults). A setting value may now be a qualified name. DefaultPage is required: `open workflow` without it is CE1834, so the visitor refuses it and describe prints a stored page-less one as a NOT re-executable note. Commit is never written on a workflow call (Mendix 9.12 removed it); AssignOnOpen/OpenWhenAssigned are left unwritten below 9.20, which introduced them. Measured: - Tests seed Studio Pro-authored actions with non-default flags; with the describe case stubbed back out they fail with the symptom ($Type = Forms$NoAction, AssignOnOpen = <nil>). - TestApp round trip of TaskInbox/TaskDashboard/ConflictedWorkflowDefinition View: OpenUserTaskClientAction 6 -> 6 on both (fault-forced build: 6 -> 4). mx check 11.15.0-rc.4: control 3 errors (CE0067 x3), fixed 3, fault 3 — mx check cannot see a lost action, the BSON count is the evidence. - Fresh 11.13.0 app, bug-test exec'd: mx check 0 errors; describe -> exec of all five pages "Unchanged page"; `mx convert -p` of a copy re-serializes all 8 written actions to the same key set and values (key-sorted), so the property sets are Studio Pro's. Without DefaultPage: CE1834; outside a WorkflowUserTask / Workflow data container: CE1843. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82sUVQEB3K5W5vh85wM
…th fix widgets (#832) widget's stored schema, as Studio Pro does, instead of upgrading it to the installed .mpk, and users need to know what upgrades it instead. The guide already said a rewrite keeps the schema "until you sync it", but its remedy predated `mxcli fix widgets`: it pointed at the partial `mxcli widget sync`, at Studio Pro, and warned off `mx update-widgets`. `mxcli fix widgets` runs Mendix's own `mx update-widgets` and restores the MPR v2 layout (its --help, and the marketplace guide's "Repairing the model"); `widget sync` clears 7 of 40 CE0463 on the reference fixture by its own --help. The guide now leads with `fix widgets`, says that earlier beta builds upgraded widgets as a side effect of a rewrite (the template is reconciled against the installed .mpk, per the guide's own mechanism section) and that a passing `docker check` does not prove the stored project clean. The create-page skill gets the same one-paragraph rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82sUVQEB3K5W5vh85wM
…tions left out (#854) Symptom: an action on a data grid filter (`OnChange:` on a text, number, date or drop-down filter), on a barcode scanner (`onDetect:`) or on a combo box's onEnterEvent / onLeaveEvent / onChangeFilterInputEvent was refused under `mdl 1;` and dropped with a warning under mdl 0. On an 11.13.0 app the bug-test page gave "9 issues: 4 errors, 5 warnings" (4x MDL-WIDGET37 for the filters, 4x MDL-WIDGET06 for the named slots); without the header it was written with every action missing. describe printed no filter action, so a Studio Pro-authored one could not be restated. Cause: these widgets' definitions are hand-written and embedded (sdk/widgets/definitions), and a hand-written definition beats the generator, which maps every action slot of a generated widget. Theirs had no mapping for these slots, so nothing read the action. Describe's filter branch read no action, and its known-type output branch printed no named slots. Fix: the four filters map `onChange` from `OnChange:` (in every mode of the drop-down filter); the barcode scanner maps `onDetect` and the combo box `onEnterEvent` / `onLeaveEvent` / `onChangeFilterInputEvent` by their own keys, in all three combo box modes — the spelling the generator gives the same slots. Describe reads them back. A slot a definition sources from `OnChange:` under a key the generic matcher does not know (the database-mode `onChangeDatabaseEvent`) is not also printed by key. The issue's second bullet — a Studio Pro-authored filter onChange lost when its widget is rebuilt — already held on main through the per-property patch of #832: seeding a real Forms$MicroflowAction into a stored filter, then rewriting the page from describe with the filter edited, keeps it (TestIssue854_EditedFilterKeepsItsStoredOnChange). Control: stubbing patchStoredPluggable fails it with "editing tfTitle reset its onChange to Forms$NoAction"; the sibling-edit variant fails only with the patch AND the passthrough stubbed. What this change adds is that describe can say the action, so a statement can keep, retarget or remove it. The combo box's onChangeDatabaseEvent was already mapped by mendixlabs#1583. Measured (Mendix 11.13.0, mxcli new app, mx check --no-update-widgets and with the widget update): all eight actions stored, 0 errors, describe -> exec "Unchanged page". Fault variant (definitions and describe at HEAD): refused under mdl 1, 0 errors under mdl 0 with the actions missing. TestBuiltinDefsMapEveryActionSlot audits every embedded definition against the action properties its .mpk declares, and requires a by-key slot in every mode, so the next unmapped slot fails a test rather than a user. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82sUVQEB3K5W5vh85wM
… slot, and MDL-WIDGET36 applies to ALTER (#854) Symptom: `alter page … set (Action: call nanoflow M.Open) on gallery1` was refused — "widget "gallery1" (CustomWidgets$CustomWidget) has no on-click action — Action can only be set on a widget that has one: a button, a container, a list view or an image" — while `set ('onClick': …)` wrote the very same slot. And no ALTER spelling applied MDL-WIDGET36: on an 11.13.0 app, `mdl 1; alter page … set ('onClick': …) on gSingle` (default Selection Single, trigger single) reported "Altered page", and mx check then failed: "The item click action is ambiguous. Change "On click trigger" to "Double click" or set "Selection" to "None"." at Gallery 'gSingle' — 1 error. Cause: ALTER routed the `Action` key to SetWidgetAction, which writes a built-in widget's own click property (Action / OnClickAction / ClickAction). A pluggable widget has none; its click is the action-typed property its definition reads `onClick:` from. MDL-WIDGET36 lived only in the CREATE validator, which reads the statement's widget tree — a SET carries no widget, and may name only one of the three settings the Gallery's own rule turns on. Fix: `Action:` and its alias `onClick:` go to the stored pluggable widget's click slot (the one action property actionSourceForKey reads `onClick:` from), and keep SetWidgetAction on a built-in widget; a pluggable widget without a click slot is refused naming the action slots it has. After a SET that changes a gallery's click, selection or trigger, the stored gallery is judged as the SET leaves it, with the Gallery editorConfig's own condition (`"None" !== itemSelection && onClick && "single" === onClickTrigger`): refused under `mdl 1;` before the page is saved, written with the MDL-V1-GALLERYCLICK warning under mdl 0 — what `create page` does. check predicts both on a probe copy of the stored page. The page mutator gains a PluggableWidgetState capability that reports what a stored pluggable widget holds. Measured (Mendix 11.13.0, mx check --no-update-widgets): `set (Action: …)` on a Selection None gallery, and `set (onClickTrigger: 'double', Action: …)` on a single-selection one, both under `mdl 1;` — 0 errors; the ambiguous `set (Action: …)` under `mdl 1;` — refused, nothing written; the same under mdl 0 (fault forced in) — written with the warning, and mx check reports the ambiguity, 1 error. Pre-fix binary: both legal SETs refused ("has no on-click action"), the quoted form written without MDL-WIDGET36 and mx check failing as above. Tests: TestIssue854_AlterSetActionOnGallery (Action / onClick / 'onClick'), _AlterSetActionControls (a button keeps its setter, a combo box is still refused), _AlterSetGalleryClickAmbiguity (mdl 1 refuses both spellings, mdl 0 writes and warns, Selection None control), _CheckAlterSetGalleryClickAmbiguity. Before the fix they failed with the reported refusal, and the 'onClick' spelling under mdl 1 returned no error where MDL-WIDGET36 was wanted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82sUVQEB3K5W5vh85wM
… it declares, refuse one it does not (#854) Symptom: an enumeration property of a pluggable widget was stored exactly as the script spelt it, and nothing compared the value with the widget's keys. On an 11.13.0 app, `gallery g (…, onClickTrigger: Double, …)` stored "Double", `onClickTrigger: triple` stored "triple" and a data grid's `pagination: 'Buttons'` stored "Buttons" — mx check reported 0 errors for all three, with and without its widget update. The Gallery's runtime (Gallery.mjs, 3.x) runs the row click only for `"single" === clickTrigger` or `"double" === clickTrigger`, so with "Double" the row action never ran on a click. The issue named the hand-written definitions (the gallery's onClickTrigger); the generated ones (the data grid) had the same gap. Cause: the engine's primitive writes — the mapping pass and the explicit-property pass — and ALTER's pluggable setter wrote the value as given, and no check rule looked at a widget's own enumeration property (MDL-WIDGET08 covered object-list items only). Fix, split by kind as ADR-0011 asks: - a value that names a declared key in another case is a wrong write, not a new meaning: it is stored as the key under every language version, by `create page` (the builder now reports its schema's enumeration keys, read from the Type the build writes, which the loader has aligned with the installed package) and by `alter page … set` (PluggablePropertyScope carries the keys); - a value that names no key is a new rejection, gated as MDL-V1-WIDGETENUM: refused under `mdl 1;` as MDL-WIDGET08, naming the keys, with nothing written; written as given with a warning under mdl 0. `check -p` predicts it from the installed package; a check without a project cannot know a newer widget's keys and says nothing. The migration reference is regenerated with the new change. Measured (11.13.0, mx check --no-update-widgets): with the fix, "Double" and "Buttons" are stored as "double" / "buttons", 0 errors; `triple` under `mdl 1;` is refused by check ("valid values are single, double") and nothing is written; under mdl 0 it is written with one MDL-V1-WIDGETENUM warning. The earlier run (fault in place) stored all three verbatim, also 0 errors — mx check is not the oracle here, the widget's runtime bundle is. A check -p sweep of all 1100 example scripts reports the new rule nowhere. Tests (failing before the fix with `onClickTrigger stored "Double", want the key "double"`, `pagination stored "Buttons"`, `set pagination stored "VirtualScrolling"` and no MDL-WIDGET08 refusal): TestIssue854_EnumValueIsStoredAsItsKey (both headers; hand-written and generated definition), _UndeclaredEnumValue, _CheckUndeclaredEnumValue (with a case-variant control), _AlterSetEnumValue. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82sUVQEB3K5W5vh85wM
The fix commits for #1209 (version-shape pages, KeyboardType) and #832 (workflow button actions) added no Unreleased entry. Neither did #1754 (workflows below 11.3), merged earlier in PR #1757. The entries follow the file's style. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82sUVQEB3K5W5vh85wM
The struct-field alignment the go1.27.3 toolchain's gofmt (CI's) expects. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82sUVQEB3K5W5vh85wM
docs: recover a merge whose base an older mxcli wrote (fix property-sets)
fix: page properties lost on rewrite — Mendix 9.x/10.x shapes, workflow button actions, pluggable widget events
Symptom (#1756, mendixlabs#1664): a profile's application title -- Navigation$NavigationProfile.AppTitle, "Mendix" in a new project, shown by the runtime as "Mendix - <page title>" in every browser tab -- had no MDL form. `create or modify navigation Responsive app title 'EWO' ...` failed with "extraneous input 'app' expecting the start of a statement", `describe navigation` printed neither the title nor the icon (AppIcon), and `create or modify translations ... for en_US` refuses the source language, so every generated app kept "Mendix" in the tab unless someone opened Studio Pro. Cause: navigationClause had no alternative for either property, the reader did not read them, and the writer never wrote them (only a profile mxcli adds got an empty AppTitle and AppIcon). Fix: `app title '<text>'` and `app icon <Module.Collection.Image> | none`, order-free with the other clauses. No new token: APP, TITLE and ICON were already lexer keywords and are all in `keyword`, so `app`/`icon` stay usable as names (tested). The title is written as the project default language's item of the stored Texts$Text with bsonnav.SetTextsTextTranslation -- the rule ALTER's texts use -- keeping its $ID and every other language's item. An omitted clause keeps the stored value (#1522's rule). The icon is resolved with resolveImageRefs, as a page's image reference is: check --references reports a missing one (script-created collections count) and exec refuses it before writing. Describe prints both, first, whenever stored (Studio Pro's 'Mendix' / Atlas_Core.Content.Mendix included); an empty title or icon is omitted, which replays as "keep". A native profile has neither property, so both clauses are refused there; the MCP backend refuses them rather than dropping them. AppTitle/AppIcon were introduced in 8.12.0, below mxcli's floor, so there is no version gate. Tests: visitor (clauses, order, escaping, none, identifiers still parse), executor with MockBackend (spec, native refusal, icon resolution at exec and in --references, describe + reparse), backend on encoded BSON (default language item patched in place, other languages and $IDs kept, silent statement keeps both) and end to end on the fixture project (nl_NL item survives, restating is elided, a changed title writes), MCP refusal. Controls: before the grammar change every visitor case failed with "extraneous input 'app'"; replacing the in-place patch with a fresh Texts$Text fails the encoded-BSON test (nl_NL item and stored $IDs lost) while the end-to-end test still passes, because canon.CarryTranslations restores the other language on the real write path; stubbing the icon resolution fails both resolution tests; removing the MCP refusal fails its test with a PED read before any refusal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82sUVQEB3K5W5vh85wM
The clauses added for #1756 in the places a user or an agent looks for navigation syntax: the manage-navigation skill (its routing description now names the browser tab title, a section, the setup pattern, the native-profile refusal list and a checklist line), the docs-site CREATE NAVIGATION reference, the quick reference table and example, and the `mxcli syntax navigation.create` entry. They say what is not obvious from the grammar: the title is the prefix of every browser tab ("Mendix - <page title>" in a new project), it is written in the project's default language with the other languages kept, and translating it needs an unscoped `create or modify translations` because the navigation is a project-level document. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82sUVQEB3K5W5vh85wM
The CHANGELOG "Fixed" entry and the fix-issue finding for #1756 (mendixlabs#1664), kept apart from the code so they can be squashed into it on integration. The finding records the controls: a fresh Texts$Text in place of the in-place patch is caught only by the test on navPatchWebProfile's output, since canon.CarryTranslations restores the other language on the real write path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82sUVQEB3K5W5vh85wM
The #1756 clauses landed without a real mx check, so I ran one on Mendix 11.13.0. The bug-test, which set the 3164×1086 docs/images/mxcli-cli.png as the app icon, executed cleanly, but mx check then reported: CE6859 "The selected image must be a square PNG image that is at least 512 pixels wide." at Navigation profile 'Responsive' Studio Pro's own Atlas_Core.Content.Mendix passed, with 0 errors. exec now reads the PNG header of the stored image and refuses one that is not a square PNG of at least 512 px, naming its size. On a fresh 11.13 app the script that creates the collection and sets the icon is refused and rolled back, so no collection is left behind. A generated 512×512 PNG and the default icon both pass mx check with 0 errors. An image with no bytes is left to mx check. One the script itself creates is judged when the navigation statement runs, by which time it is stored. Also measured: a dangling AppIcon is CE1613 "The selected image … no longer exists." So mx check does catch a missing icon. The previous commit's "reported only by the next build" was wrong, and the comment is corrected. The exec refusal is about failing early. The bug-test now uses the default icon. On a fresh 11.13 app: - mx check reports 0 errors, the same as the blank app; - a later statement without the clauses is "Unchanged"; - describe → exec of the navigation is "Unchanged". The finding and the docs gain the icon rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82sUVQEB3K5W5vh85wM
…1744) Symptom (mendixlabs#1663, Mendix 11.14.0, Combo box 2.10.0): a combo box's custom content - how it shows more than one attribute per option - could not be written. `mxcli widget describe combobox` listed optionsSourceAssociationCustomContent as a `widgets` property, but combobox cbPerson (…) { optionssourceassociationcustomcontent cc { dynamictext … } } was refused by `check -p`: MDL-WIDGET26 "`optionssourceassociationcustomcontent` is not a container of `combobox`, which declares no containers", and exec failed on the block ("unsupported widget type"). describe printed stored content only as a NOT SHOWN note, so a combo box Studio Pro gave content could not be restated, and a rewrite that changed it was refused (#1648). Cause: the combo box's built-in definition declared no child slots; the content keys were listed as known-but-unmapped properties. The custom content belongs to an option-source MODE (widget.xml binds it to that mode's datasource), and nothing read a mode's child slots except the engine itself: the unrouted-children rule, the container check, `widget describe` and the registry's keyword lower-casing all read the definition's own slots only. Fix: - combobox.def.json (both copies, now identical): association mode declares `optionssourceassociationcustomcontent`, database mode `optionssourcedatabasecustomcontent`. The engine already builds a mode's slots, after the mode's datasource, so the content binds to the option entity. - A mode's slot is a container of the widget (MDL-WIDGET26 accepts it); the slot of another mode, or any slot on an enumeration combo box, is MDL-WIDGET30 at check and refused at exec, naming the slot the mode has (one predicate, mode-aware: selectedChildSlots mirrors selectMappings). - The slot's key written as a value is MDL-WIDGET27, as for any container, and the explicit-property pass no longer writes a scalar into a widgets property's PrimitiveValue. - describe prints the described mode's content as its block; content of any other slot keeps the NOT SHOWN note. The passthrough's #1648 refusal now covers only content describe did not print (undescribedContent), since a statement restates the rest. - `widget describe` lists the two slots, marked per mode, and leaves them out of its enumeration-mode example. Measured on a fresh Mendix 11.13.0 app (Combo box 2.5.0, the version 11.13 ships; 2.10.0 was not available here), bug-test mdl-examples/bug-tests/1744-combobox-custom-content.mdl: - fault forced back (definition without the slots): check -p reports the two MDL-WIDGET26 errors above; exec --no-check fails on the block. - fixed: check -p 0 errors; exec "Created page"; `mxcli docker check --no-update-widgets` and with update-widgets 0 errors (blank app: 0); `mxcli fix widgets` (mx update-widgets in place) changes nothing in the page's BSON; describe -> exec "Unchanged page"; the description with the association combo box's label changed -> "Replaced page", content kept, 0 errors. - not covered: the content type written without content (CE0642) and content under type 'no' (measured CE0463) - the next commit. A static-mode combo box's per-value content: static values have no MDL spelling yet. Tests: widget_combobox_custom_content_1744_test.go (write in both modes, check accepts, wrong-mode refusal at check and exec, describe round trip, other mode's content stays named, slot key as value, passthrough). Control: with the definition reverted the seven that read it fail, the check test with "MDL-WIDGET26 … which declares no containers"; the passthrough test reads no definition and carries its own control (content describe did not print stays refused). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82sUVQEB3K5W5vh85wM
…ntent (#1744) Symptom (mendixlabs#1663): the enumeration that switches a combo box's custom content on was written on its own, so combobox cbPerson (…, optionsSourceAssociationCustomContentType: 'yes') passed check and exec, and mx check reported CE0642 "Property 'Custom content' is required." at Widgets container 'Custom content' of combo box 'cbPerson'. Cause: nothing tied the …CustomContentType enumeration to the slot it shows. The content is required while the type is 'yes' or 'listItem' and hidden while it is 'no' - and the previous commit made the content writable without the type, which leaves the template's 'no' in place. Fix: a child slot may declare a `switch` (property, off, on, caption); the combo box's two custom-content slots declare theirs. One predicate, slotSwitchProblem, read by check (MDL-WIDGET53, new: MDL-WIDGET16 is the combo box's caption/datasource rule and the rule-ID guard keeps one owner per ID) and by exec (refused before anything is written, also under --no-check): - the switch on with no content: refused, naming CE0642 and the block; - content under the switch off: refused - the editor hides it; - content with the switch left out: the build writes it on ('yes'). describe prints content stored under 'no' in the NOT SHOWN note instead of as a block, which would re-execute as shown content. Measured on a fresh Mendix 11.13.0 app with Combo box 2.5.0: - the type alone, fault forced back (definition without the slots): check -p clean, exec "Created page", `mxcli docker check --no-update-widgets` CE0642 exactly as reported. Fixed: check -p and exec --no-check refuse it. - content with the type 'no', and with the type left out, on the previous commit: CE0463 at both combo boxes. Fixed: 'no' is refused; left out is written 'yes' and the bug-test page (three combo boxes, both modes) is 0 errors, `mxcli fix widgets` (mx update-widgets in place) leaves its BSON identical (10505 ndsl lines, 0 diff), describe -> exec "Unchanged page". Tests: widget_combobox_custom_content_type_1744_test.go (on without content in both modes and for 'listItem', content under 'no', content switching the type on, describe of content under 'no', controls). Control: with the switches removed from the definition all of them but the controls fail - exec returns nil, check reports nothing, the type stays "no". Bug tests: 1744-combobox-custom-content.mdl gains the type-left-out combo box; 1744-combobox-custom-content-type-without-content.fail.mdl is the reported shape, which check must refuse. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82sUVQEB3K5W5vh85wM
Left by a conflict resolution; it split the Fixed list in two. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82sUVQEB3K5W5vh85wM
…1743) Symptom (mendixlabs#1662, reported on v0.28.0 / Mendix 11.14.0): a text box's Events -> "On enter key press" (Forms$TextBox.OnEnterKeyPressAction) had no MDL property. `OnEnterKeyPress:`, `OnEnterKeyPressAction:` and `OnEnterKey:` were each reported as "`OnEnterKeyPress` is not a property mxcli writes on a textbox (Forms$TextBox), so it would be dropped", exec dropped it, describe showed nothing and mx check passed, so "a search box that should search on Enter cannot be generated". `OnChange:` on the same widget was written and described. Cause: nothing read it anywhere. No builder key, no describe read, and the TextBox case of widgetToGen hard-coded SetOnEnterKeyPressAction(noActionGen()), so describe -> exec of a Studio Pro text box with an enter-key action also replaced it with nothing. carryNoActionExecution carries only the flag between two NoActions, never a stored action. Fix: `OnEnterKeyPress:` takes the action forms `OnChange:` takes; the stored name `OnEnterKeyPressAction:` is the same property (both at once is MDL-WIDGET18). No grammar keyword: the generic `key: action` branch already parses it, and a flow call written without `call` arrives as a data source that actionFromFlowDataSource converts. A value that is not an action is MDL-WIDGET28 at check and refused at exec. The builder reads it through a small table of input event actions (input_event_actions.go), the writer writes it, describe prints it back. The metamodel gives the slot to Forms$TextBox alone - gen's TextArea has no SetOnEnterKeyPressAction - so on a text area (the report says it has the same property) and every other widget the per-kind check refuses the key and says why. The keys stay out of staticWidgetKnownProps, the cross-widget union. ALTER `set (OnChange: ...) on <textbox>` is refused today ("not a pluggable widget and has no named action slots"); `OnEnterKeyPress` gets the same refusal, so ALTER is unchanged. Measured on a fresh 11.13.0 app: the repro's three enter-key actions are written, `mxcli docker check` reports "The app contains: 0 errors.", describe prints them as `OnEnterKeyPress: ...`, and describe -> exec reports "Unchanged page". Control, with the writer's NoAction and the unread describe forced back in: describe of the same page prints none of the three, exec reports "Replaced page", all three are gone, and mx check still reports 0 errors. The new executor and writer tests fail against the unfixed code with the reported message. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82sUVQEB3K5W5vh85wM
…> exec (#1743) Symptom, found while fixing the enter-key action: an input widget's Studio Pro Events -> "On enter" and "On leave" (focus in / focus out; OnEnterAction and OnLeaveAction on Forms$TextBox, TextArea, DatePicker, CheckBox, RadioButtonGroup and DropDown) had no MDL property, and describe -> exec of a Studio Pro page deleted every one. Measured on a fresh 11.13.0 app with the previous commit's build: a page holding seven of them described with none, exec reported "Replaced page", all seven were gone, and `mxcli docker check` still reported "The app contains: 0 errors." Cause: the same as the enter-key slot. widgetToGen hard-coded SetOnEnterAction(noActionGen()) / SetOnLeaveAction(noActionGen()) on every input (only the text box's OnEnterAction read a model field, which no builder set), describe never read either slot, and carryNoActionExecution copies only the DisabledDuringExecution flag between two NoActions, so a stored action met a rebuilt NoAction and was skipped. Fix: `OnEnter:` and `OnLeave:` on all six inputs, as two more rows of the input event-action table the previous commit added (stored names `OnEnterAction:` / `OnLeaveAction:` accepted, the action forms `OnChange:` takes, MDL-WIDGET28 / MDL-WIDGET18 as for the enter-key action). Every input builder reads them (applyInputFocusEventsV3, now part of inputReads), the writer writes them (focusEventsToGen, dropDownToGen), describe prints them after OnChange. On a widget without the slots, such as a button, the per-kind check refuses the key and says only an input widget has it. Measured on a fresh 11.13.0 app: the seven actions are written, mx check reports 0 errors, describe prints them, and describe -> exec reports "Unchanged page". The control is the previous commit's build over the same page (above). The new executor and writer tests fail against the unfixed code: the builder leaves both fields nil, describe prints neither, the writer writes NoActions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82sUVQEB3K5W5vh85wM
fix: text box enter/focus actions, combo box custom content, navigation app title and icon
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Syncs
ako/mxcli:maininto upstream: 11 commits from fork PRs ako#1758 and ako#1759.Page properties lost on rewrite (ako#1759)
These are three failures of the same kind: a page property that
describedidn't print, or that the writer rebuilt, so a describe → exec round trip lost it. Each commit does one thing and has a test written first, a control, a finding, a bug-test script, and a realmx checkof both the fixed and the fault variant.Mendix 9.x / 10.x page shapes
Five page properties kept their meaning but changed storage shape at a version, and mxcli read and wrote only the newer shape. The older shapes were measured on a Studio Pro-authored 9.24.30 app:
Type/StringValue/BooleanValuePageParameter/SnippetParameternamesEditableboolPlaceholder(Texts$Text)ForceFullObjectsWhat this broke on 9.24:
alter stylingon a stored 9.x design property reported success and changed nothing.The fix: a new
canon.LowerToProjectShaperuns on every unit write, before the property floor andReconcile. So every writer gets the project's shape.A text box's
KeyboardTypenow survives describe → exec as well. A rebuilt native text box used to lose it.Workflow button actions
The workflow button actions now have an MDL spelling, so a rewrite keeps them. Re-running an unchanged
describe page WorkflowCommons.TaskInboxused to report "Replaced page" and leave 4 of 6Forms$OpenUserTaskClientAction.A rewrite keeps a widget's stored schema, and the docs say to update it with
fix widgets.Pluggable widget events and enumerations
Action slots the built-in definitions left out are now written and described. These are:
OnChange:;onDetect:;Before, they were refused under
mdl 1;and dropped with a warning under mdl 0.alter page … set (Action: …)reaches a pluggable widget's click slot, such as a gallery's. It used to be refused. MDL-WIDGET36 now applies to ALTER too.An enumeration value is written as the key the widget declares. For example,
onClickTrigger: Doubleis stored as the declared key, and one the widget doesn't declare is refused. Before, the value was stored exactly as the script spelled it.Docs: recovering a merge whose base an older mxcli wrote (ako#1758)
The problem: a Studio Pro rebase failed with "Objects with ID … of type DomainModels$AccessRule do not have the same properties", and afterwards the project wouldn't reopen.
The cause: the root cause is #1373, which was fixed in v0.26.0, but the merge base holds an access rule that a pre-0.26 mxcli wrote.
fix property-sets, like any Studio Pro save, only completes revisions from its own commit on.What's documented:
docs-site/src/tools/outside-studio-pro.mdexplains that the repair reaches forward, not back, and gives five steps to get past a merge that already fails.fix property-sets --helpgives the same advice in short form.How it was validated: with
mx merge, which runs Studio Pro's merge engine, on mxbuild 11.13.0:Also