Form grammar#
Form grammar describes form declarations, sections, fields, actions, validation bindings, and layout-oriented form members.
Source#
| Property | Value |
|---|---|
| Grammar file | packages/business/language/grammar/form.g4 |
| Grammar name | form |
| Grammar kind | parser |
| Imports | common, type, expression, literal, function |
| Imported by | app, BusinessLanguage, module |
| Direct rule or token count | 46 |
How to use this page#
Read the examples first when authoring Business Language. Use the rule inventory when checking exact grammar coverage or when updating parser, lowering, editor, or documentation behavior.
Entry rules and syntax families#
Start with these rules when reading this grammar: formDeclaration, formFieldType, formSourceExpression, formStateDeclaration, buttonDeclaration, buttonTemplateDeclaration, buttonInstanceDeclaration, buttonParameterClause, buttonMenuDeclaration, buttonMenuOptionDeclaration.
- Declarations:
buttonDeclaration,buttonInstanceDeclaration,buttonMenuDeclaration,buttonMenuOptionDeclaration,buttonMenuSeparatorDeclaration,buttonTemplateDeclaration,formDeclaration,formStateDeclaration - Expressions:
formSourceExpression - Clauses:
buttonParameterClause - Types:
formFieldType
Key grammar excerpts#
formDeclaration#
formDeclaration
: annotation* accessModifier? FORM identifier formModifier* formBase? formDeclarationWithHeader
| annotation* accessModifier? FORM identifier formModifier* formBase? formDeclarationWithoutHeader
// @define @name_fields(identifier) @role(member_owner) @role(source_owner_alias_scope:form) @role(source_owner_member:ui) @kind(layout:form) @symbol(kind=global) @scope(level=2)
;formFieldType#
formFieldType
: formControlTypeReference
| typeExpression
| SELECT
; // open-ended control typeformSourceExpression#
formSourceExpression
: qualifiedIdentifier arguments postfixSuffix*
| identifierName arguments postfixSuffix*
| qualifiedIdentifier
| identifierName
| queryExpression
| querySubqueryExpression
| literal
;Complete rule and token inventory#
buttonDeclaration, buttonEvent, buttonInstanceDeclaration, buttonMember, buttonMenuDeclaration, buttonMenuMember, buttonMenuOptionDeclaration, buttonMenuOptionMember
buttonMenuSeparatorDeclaration, buttonParameterClause, buttonProperty, buttonPropertyKey, buttonTemplateDeclaration, formBase, formBodyMember, formBodySection
formControlTypeReference, formDeclaration, formDeclarationWithHeader, formDeclarationWithoutHeader, formEvent, formField, formFieldFrom, formFieldModifier
formFieldProperties, formFieldProperty, formFieldPropertyBlock, formFieldPropertyKey, formFieldType, formHeader, formHeaderProperty, formInlineBodyItem
formInlineControlField, formInlineHeaderProperty, formInlineHeaderValue, formInlineItem, formLayoutSection, formMember, formModifier, formSection
formSectionMember, formSourceExpression, formStateDeclaration, formToolbarSection, layoutConfig, layoutPropertyExamples#
Form declaration with source fields#
form VendorForm: Vendor {
body: {
vendor_id: Text from Vendor.vendor_id;
vendor_name: Text from Vendor.vendor_name;
}
}Section and button#
form InvoiceForm: Invoice {
section posting {
invoice_total: MoneyInput from Invoice.invoice_total;
}
button Post {
on click {
post_invoice(invoice_id);
}
}
}Section with state, event, layout, and button#
form VendorEditor {
body: {
section review {
selected_vendor_id: VendorId;
vendor_name: Text from Vendor.vendor_name;
on change {
refresh_preview();
}
layout: {
columns: 2;
};
button Refresh {
on click {
refresh_preview();
}
}
}
}
}Function, query, and literal sources#
form VendorSources {
body: {
vendor: Select from find_vendors(true);
vendor_ids: DataGrid from from vendor in vendors select vendor.vendor_id;
status: Select from ["draft", "active"];
}
}Header form with property blocks#
form VendorForm readonly : BaseVendorForm {
title: "Vendor";
} {
state {
selected_vendor_id: VendorId;
}
body: {
@label("Vendor")
required vendor_name: TextInput from Vendor.vendor_name {
label: "Vendor name";
on change {
validate_vendor();
}
display format {
uppercase: true;
}
}
customer_group: from CustomerMaster;
customer_count: Number from count_customers();
}
layout: {
columns: 2;
};
}Button template, instance, and menu#
form VendorActions {
button ActionButton<T>(label: string) {
label: label;
on click {
run_action();
}
}
toolbar {
save: PrimaryButton() {
label: "Save";
menu {
option save_and_close {
label: "Save and close";
on click {
save_and_close();
}
}
separator;
}
}
}
}Common authoring mistakes#
- Do not copy examples without checking the rule inventory for the exact grammar boundary.
- Do not add behavior that depends on missing configuration or undeclared user-facing errors.
Related guides#
- /language/apps-forms-controls/
- /language/source-ui-layouts/
Authoring notes#
- Keep examples aligned with the grammar source, not with inferred syntax from another language.
- Use declared messages for user-facing failures, and fail closed when required configuration is absent.