N NezamDocumentation

Form grammar#

Form grammar describes form declarations, sections, fields, actions, validation bindings, and layout-oriented form members.

Source#

PropertyValue
Grammar filepackages/business/language/grammar/form.g4
Grammar nameform
Grammar kindparser
Importscommon, type, expression, literal, function
Imported byapp, BusinessLanguage, module
Direct rule or token count46

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#

antlr
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#

antlr
formFieldType
    : formControlTypeReference
    | typeExpression
    | SELECT
    ; // open-ended control type

formSourceExpression#

antlr
formSourceExpression
    : qualifiedIdentifier arguments postfixSuffix*
    | identifierName arguments postfixSuffix*
    | qualifiedIdentifier
    | identifierName
    | queryExpression
    | querySubqueryExpression
    | literal
    ;

Complete rule and token inventory#

text
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, layoutProperty

Examples#

Form declaration with source fields#

bl
form VendorForm: Vendor {
  body: {
    vendor_id: Text from Vendor.vendor_id;
    vendor_name: Text from Vendor.vendor_name;
  }
}

Section and button#

bl
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#

bl
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#

bl
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#

bl
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#

bl
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.
  • /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.
Source: packages/business/language/grammar-files/form.md