Skip to content

Refuse an input binding with no object to bind to (MDL-WIDGET34) - #694

Merged
ako merged 4 commits into
mainfrom
fix/input-binding-without-context
Sep 25, 2026
Merged

ako merged 4 commits into
mainfrom
fix/input-binding-without-context

Conversation

@ako

@ako ako commented Sep 25, 2026

Copy link
Copy Markdown
Owner

Symptom

An input widget bound to an attribute with no object to bind to, such as textbox t (Attribute: FullName) on a page outside any data container, reported success and was written with AttributeRef: null. The binding was silently dropped.

Every input kind does this. Measured on a copy of the stock 11.13.0 project with exec --no-check, bson dump and mx check (22 errors for the page):

widget, outside a data container mxbuild
textbox, textarea, datepicker, checkbox, radiobuttons, dropdown CE0544 "This widget can only function inside a data context" + CE7005
dynamictext Attribute: CE0402 "No value specified."
combobox CE0642 "Property 'Attribute' is required."
inside a plain container; ALTER PAGE insert at top level; snippet top level same, reference null
qualified AN.Person.FullName stored, but still CE0544 / CE2421 / CE1365 / CE7247, each with CE7006

How check behaved before:

  • Plain check: said nothing about any of these.
  • With -p --references: already refused CREATE PAGE and CREATE SNIPPET, via validate_page_context.go.
  • Unguarded: plain check, exec --no-check and ALTER PAGE.

Also broken, inside a data view: Attribute: $P/FullName and Attribute: $currentObject/FullName never parsed as attribute paths. They became a data-source expression no builder reads, so they were dropped inside data views too.

Fix

The logic is in mdl/executor/cmd_pages_input_binding_context.go.

  • At check time, new rule MDL-WIDGET34, in the widget-tree walk (no project needed). It reuses the context tracking behind MDL-PAGEARG01, which knows when a widget sits at the top of a page or snippet with no data widget around it.
    • There it refuses both bare and qualified bindings.
    • It refuses $x/Attr anywhere.
    • For ALTER PAGE inserts the surrounding context isn't known at check time, so the builder refuses those.
  • At build time: the six input builders, dynamictext and the combobox's primary Attribute: return an error naming the widget, e.g.:

    textbox 't': attribute 'FullName' has no entity to bind against — the widget is not inside a data view, list view, gallery or data grid … Place it inside a data container, e.g. dataview dv (DataSource: $Param) { textbox t (Attribute: FullName) }

  • Not simply "no entity in scope": the entity is also empty inside a data view whose data-source flow can't be resolved (the excluded ShareFeedback_Logo). describe writes qualified names there and they must keep building (Round-trip a page over a flow the project lacks: keep bindings qualified #678). So where context is unknown (ALTER), only a bare name with no entity is refused, since that one is always written as null.

Evidence

Control. With the fix stubbed out, 12 tests or subtests fail with the reported symptom.

Two existing tests built input widgets with no entity in scope. TestBuildDynamicTextV3_AttributeBinds counted a bare Title reference as "bound", so it was asserting the bug. Both now set an entity, and the dynamictext test checks the stored reference is M.Item.Title.

Real run (copy of the project):

  • Refused: plain check reports MDL-WIDGET34 for all 11 CREATE cases. exec --no-check --continue-on-error refuses every bad statement, the ALTER insert included, and writes none of them.
  • Controls, all 0 errors in mx check:
    • a list view, a gallery and a data grid;
    • a data view with a bare textbox, a qualified textbox, a combobox and a dynamictext;
    • a snippet with a data view over its parameter;
    • an ALTER insert into a data view.
  • Round trip: describe → exec of all 17 pages passes (17/17, as on main), plus all 4 snippets.

Bug-tests: mdl-examples/bug-tests/input-binding-without-context.mdl (valid; execs to 0 errors) and input-binding-without-context.fail.mdl (refused). CHANGELOG entry added.

Not covered

  • A qualified attribute inserted by ALTER PAGE at the top level still gets through and fails the build (CE0544). mxcli can't yet tell from the stored page that the insert point is outside every data widget.
  • Binding straight to a page parameter ($P/Attr) looks legal in Mendix, going by CE0544's wording, but mxcli can't write it. It's refused rather than silently dropped.

Checklist

  • Failing tests first (builder, check rule)
  • Control recorded
  • Real runs on copies; 17-page round trip unchanged
  • Bug-test MDL pair; make check-mdl passes
  • Finding appended; make check-findings passes
  • make build && make test && make lint pass, each exit code checked separately

🤖 Generated with Claude Code

ako and others added 4 commits September 25, 2026 14:15
…L-WIDGET34)

`textbox t (Attribute: FullName)` at the top of a page, snippet or plain
container has no entity to qualify the name with; the writer stores anything
shorter than Module.Entity.Attribute as `AttributeRef: null`. Plain `check`
passed, `exec --no-check` and `alter page … insert` said success, and
mxbuild 11.13.0 failed the page: CE0544 + CE7005 on text box, text area,
date picker, check box, radio buttons and drop-down, CE0402 on a dynamic
text, CE0642 on a combo box. A qualified attribute there is stored and fails
as well (CE0544 / CE2421 / CE1365 / CE7247 + CE7006). `Attribute: $P/Name`
and `$currentObject/Name` parse as a data-source expression no builder reads,
so they were dropped even inside a data view.

- check: MDL-WIDGET34 in the widget-tree walk (no project needed), using the
  MDL-PAGEARG01 three-state context — refuses bare and qualified bindings at
  a document root outside any data widget, and the `$x/Attr` spelling
  anywhere. ALTER's subtree walk (unknown context) stands down.
- build: the six input builders, dynamic text and the pluggable engine's
  primary `Attribute:` mapping refuse with the widget named, so nothing is
  written; with an unknown context only a bare name with no entity is
  refused, so qualified bindings inside an unresolvable flow source (excluded
  ShareFeedback_Logo) keep building.

Two unit tests built inputs with no entity in scope and one asserted the bare
`Title` reference counted as bound; they now set an entity context.

Verified on a copy of a Mendix 11.13.0 project: 22 mxbuild errors before,
every case refused after with nothing written; controls (data view, list
view, gallery, data grid, snippet data view, ALTER into a data view) build
at 0 errors; describe -> exec round trip 17/17 pages, 4/4 snippets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ako
ako merged commit 5dc51ce into main Sep 25, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant