Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Validation Pattern

Mendix uses a two-microflow pattern for form validation: a validation microflow checks fields and returns feedback, and an action microflow calls it before saving.

The Validation Microflow

VALIDATION FEEDBACK attaches error messages to specific fields. The form highlights the field and displays the message.

CREATE MICROFLOW Sales.VAL_Order ($Order: Sales.Order)
RETURNS Boolean AS $IsValid
BEGIN
  DECLARE $IsValid Boolean = true;

  -- Required field
  IF $Order/OrderNumber = empty OR trim($Order/OrderNumber) = '' THEN
    SET $IsValid = false;
    VALIDATION FEEDBACK $Order/OrderNumber MESSAGE 'Order number is required';
  END IF;

  -- Date must be in the future
  IF $Order/DeliveryDate != empty AND $Order/DeliveryDate < [%CurrentDateTime%] THEN
    SET $IsValid = false;
    VALIDATION FEEDBACK $Order/DeliveryDate MESSAGE 'Delivery date must be in the future';
  END IF;

  -- Numeric range
  IF $Order/Quantity <= 0 THEN
    SET $IsValid = false;
    VALIDATION FEEDBACK $Order/Quantity MESSAGE 'Quantity must be greater than zero';
  END IF;

  IF $Order/Quantity > 10000 THEN
    SET $IsValid = false;
    VALIDATION FEEDBACK $Order/Quantity MESSAGE 'Maximum quantity is 10,000';
  END IF;

  -- Cross-field validation
  IF $Order/DiscountPercent > 0 AND $Order/ApprovedBy = empty THEN
    SET $IsValid = false;
    VALIDATION FEEDBACK $Order/ApprovedBy MESSAGE 'Discounted orders require approval';
  END IF;

  RETURN $IsValid;
END;
/

The Action Microflow

The action microflow calls validation, and only saves if it passes:

CREATE MICROFLOW Sales.ACT_Order_Save ($Order: Sales.Order)
RETURNS Boolean AS $IsValid
BEGIN
  $IsValid = CALL MICROFLOW Sales.VAL_Order($param = $Order);

  IF $IsValid THEN
    COMMIT $Order;
    CLOSE PAGE;
  END IF;

  RETURN $IsValid;
END;
/

Wiring It Up

The page’s Save button calls the action microflow (not the validation microflow directly):

CREATE PAGE Sales.Order_Edit (
  Params: { $Order: Sales.Order },
  Title: 'Order',
  Layout: Atlas_Core.PopupLayout
) {
  LAYOUTGRID mainGrid {
    ROW row1 {
      COLUMN col1 (DesktopWidth: AutoFill) {
        DATAVIEW dv (DataSource: $Order) {
          TEXTBOX txtOrderNumber (Label: 'Order Number', Attribute: OrderNumber)
          DATEPICKER dpDelivery (Label: 'Delivery Date', Attribute: DeliveryDate)
          TEXTBOX txtQuantity (Label: 'Quantity', Attribute: Quantity)
          TEXTBOX txtDiscount (Label: 'Discount %', Attribute: DiscountPercent)
          FOOTER footer1 {
            ACTIONBUTTON btnSave (
              Caption: 'Save',
              Action: CALL Sales.ACT_Order_Save,
              ButtonStyle: Success
            )
            ACTIONBUTTON btnCancel (Caption: 'Cancel', Action: CANCEL_CHANGES)
          }
        }
      }
    }
  }
};
/