fix(pages): honour DataView FormOrientation and showFooter (#762, #813) - #75
Merged
Conversation
…s#762, mendixlabs#813) Two DataView properties parsed, passed `mxcli check`, and were then silently discarded. Different causes, identical symptom. mendixlabs#762 — FormOrientation: Vertical had no effect on the DEFAULT (modelsdk) engine, while working under --engine legacy. Studio Pro's "Form orientation" radio has no BSON field of its own: it IS LabelWidth (0 = Vertical, 3 = Horizontal, Mendix's metamodel default). Only the legacy writer performed that translation; the modelsdk writer emitted LabelWidth solely when an explicit `LabelWidth:` was given, so the orientation was read into the model and dropped. That is the mendixlabs#812 shape again — a field set on the model that no writer on the active engine reads. The derivation now lives on the model (pages.DataView.ResolvedLabelWidth) and both writers call it, so they cannot drift apart again; the modelsdk writer emits LabelWidth unconditionally. mendixlabs#813 — showFooter was not settable at all. ShowFooter was only ever set implicitly, by the presence of a `footer { … }` block, so there was no way to show an empty footer or to declare footer widgets that start hidden. The property sits in the validator's allow-list, so it parsed clean and was thrown away. It is now read explicitly and wins over the block in both directions; hiding a footer does not discard its widgets. A trap worth recording: WidgetV3.GetBoolProp is case-SENSITIVE and accepts only a real bool, unlike GetStringProp which is case-insensitive. My first attempt found the key and still read false, so the value is now coerced from the looked-up value and a nonsense one is refused rather than defaulting to false — defaulting is the failure mode this whole fix is closing. DESCRIBE emits ShowFooter only when the implicit rule would not reproduce the stored value, so a plain footer block still round-trips as a block. Verified end-to-end against a real project, both engines producing identical BSON: LabelWidth [0, 3, 5, 3] (Vertical, Horizontal, explicit 5, default) ShowFooter [false, false, false, true] and DESCRIBE round-trips all four forms. Reverting either fix fails the new tests: 1 case for mendixlabs#762, 6 for mendixlabs#813. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012XR649rKk68z6gBpngu6MA
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.
Fixes mendixlabs#762 and mendixlabs#813.
Two DataView properties parsed, passed
mxcli check, and were then silently discarded. Same symptom, different causes — worth reading as two fixes that happen to share a file.mendixlabs#762 —
FormOrientation: Verticalhad no effect on the default engineIt worked under
--engine legacyand was dropped on the default (modelsdk) one:LabelWidthin BSON[0, 3]✅[]— absent ❌Studio Pro's "Form orientation" radio has no BSON field of its own — it is
LabelWidth(0 = Vertical, 3 = Horizontal, Mendix's metamodel default). Only the legacy writer performed that translation. The modelsdk writer emittedLabelWidthsolely when an explicitLabelWidth:was given, so the orientation was read into the model and then dropped.That is the mendixlabs#812 shape again: a field set on the model that no writer on the active engine reads. The derivation now lives on the model (
pages.DataView.ResolvedLabelWidth) and both writers call it, so they cannot drift apart a second time; the modelsdk writer emitsLabelWidthunconditionally.mendixlabs#813 —
showFooterwas not settable at allShowFooterwas only ever set implicitly, by the presence of afooter { … }block. So there was no way to show an empty footer, and no way to declare footer widgets that start hidden. The property sits in the validator's allow-list, soshowFooter: trueparsed clean and was thrown away.It is now read explicitly and wins over the block in both directions; hiding a footer does not discard its widgets.
A trap worth flagging for reviewers
WidgetV3.GetBoolPropis case-sensitive and accepts only a realbool— unlikeGetStringProp, which is case-insensitive. My first attempt found the key and still readfalse. The value is now coerced from the looked-up value, and a nonsense one is refused rather than defaulting to false — defaulting is precisely the failure mode this fix is closing. Same hazard exists for any other property read withGetBoolProp.Verification
End-to-end against a real project, both engines now producing identical BSON:
And
DESCRIBEround-trips all four forms:ShowFooteris emitted only when the implicit rule would not reproduce the stored value, so a plain footer block still round-trips as a block rather than gaining a redundant property.Mutation-checked: reverting the mendixlabs#762 fix fails 1 case, reverting mendixlabs#813 fails 6. Full suite green; corpus at 237/39 (+1 for the new repro fixture).
Docs:
create-page.mdgains theshowFootersection; a symptom row is appended at the end of the table, per the convention added in #70.🤖 Generated with Claude Code
https://claude.ai/code/session_012XR649rKk68z6gBpngu6MA
Generated by Claude Code