Skip to content

Commit 0bce1f1

Browse files
akoclaude
andcommitted
Fix ALTER PAGE SET to support Attribute property (issue #10)
Add ATTRIBUTE token to the grammar's keyword rule so it is recognized as an identifier in SET assignments, and add setWidgetAttributeRef executor handler to update AttributeRef on input widgets. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 7985512 commit 0bce1f1

4 files changed

Lines changed: 64 additions & 22 deletions

File tree

mdl/executor/cmd_alter_page.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,8 @@ func setRawWidgetProperty(widget bson.D, propName string, value interface{}) err
478478
dSet(widget, "Name", s)
479479
}
480480
return nil
481+
case "Attribute":
482+
return setWidgetAttributeRef(widget, value)
481483
default:
482484
// Try as pluggable widget property (quoted string property name)
483485
return setPluggableWidgetProperty(widget, propName, value)
@@ -496,6 +498,41 @@ func setWidgetCaption(widget bson.D, value interface{}) error {
496498
return nil
497499
}
498500

501+
// setWidgetAttributeRef sets or updates the AttributeRef on an input widget.
502+
// The value must be a fully qualified path (Module.Entity.Attribute, 2+ dots).
503+
// If not fully qualified, AttributeRef is set to nil to avoid Studio Pro crash.
504+
func setWidgetAttributeRef(widget bson.D, value interface{}) error {
505+
attrPath, ok := value.(string)
506+
if !ok {
507+
return fmt.Errorf("Attribute value must be a string")
508+
}
509+
510+
// Build the new AttributeRef value
511+
var attrRefValue interface{}
512+
if strings.Count(attrPath, ".") >= 2 {
513+
attrRefValue = bson.D{
514+
{Key: "$ID", Value: mpr.IDToBsonBinary(mpr.GenerateID())},
515+
{Key: "$Type", Value: "DomainModels$AttributeRef"},
516+
{Key: "Attribute", Value: attrPath},
517+
{Key: "EntityRef", Value: nil},
518+
}
519+
} else {
520+
// Not fully qualified — clear the ref to avoid Mendix crash
521+
attrRefValue = nil
522+
}
523+
524+
// Try to update existing AttributeRef field
525+
for i, elem := range widget {
526+
if elem.Key == "AttributeRef" {
527+
widget[i].Value = attrRefValue
528+
return nil
529+
}
530+
}
531+
532+
// No existing AttributeRef field — this widget may not support it
533+
return fmt.Errorf("widget does not have an AttributeRef property; Attribute can only be SET on input widgets (TextBox, TextArea, DatePicker, etc.)")
534+
}
535+
499536
// setWidgetLabel sets the Label.Caption text on input widgets.
500537
func setWidgetLabel(widget bson.D, value interface{}) error {
501538
label := dGetDoc(widget, "Label")

mdl/grammar/MDLParser.g4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2959,7 +2959,7 @@ keyword
29592959
| TRANSITIVE | IMPACT | SEARCH // Additional search keywords
29602960
| BUSINESS | EVENT | SUBSCRIBE | SETTINGS | CONFIGURATION // Business events / settings keywords
29612961
| DEFINE | FRAGMENT | FRAGMENTS // Fragment keywords
2962-
| INSERT | BEFORE | AFTER // ALTER PAGE keywords
2962+
| INSERT | BEFORE | AFTER | ATTRIBUTE // ALTER PAGE keywords
29632963
| WIDGETTYPE // Catalog column keyword
29642964
| URL | POSITION | SORT // Common attribute names
29652965
| GENERATE | CONNECTOR | EXEC | TABLES | VIEWS // SQL generate keywords

mdl/grammar/parser/MDLParser.interp

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)