Skip to content

Introduction to BML

BML, short for BizzStream Markup Language, is a specialized markup language designed for rendering styled elements efficiently. It is an XML-based language, sharing similarities with HTML, the standard language for creating web pages.

The primary purpose of BML is to render styled elements such as labels and listview items in a performance-oriented manner. It aims to provide a streamlined approach for displaying content without the overhead of more complex functionalities, typically found in webbrowsers. Notably, BML is adept at rendering content on both desktop and mobile web environments, ensuring a consistent user experience across different devices.

Root element

In BML , it is essential that all markup content is enclosed within the <bml> and </bml> tags. These tags serve as the root element of any BML document, defining the boundaries and scope of the markup. Within these tags, a multitude of attributes can be used.

BML and BizzStream Expressions

BML supports the inclusion of BizzStream expressions, adding dynamic content capabilities to the markup. These expressions allow for the inclusion of variable data.

BizzStream expressions within BML are enclosed by double curly brackets {{ and }}. This syntax is used to denote dynamic content that should be evaluated and replaced with actual data when rendered. For example:

<bml>
    <text>Welcome {{F["employeeName"]}}!</text>
</bml>

When BML contains BizzStream expressions, the rendering process is executed in two distinct stages:

  1. Resolving the BizzStream Expressions: In this initial stage, all BizzStream expressions embedded within the BML are evaluated. BizzStream processes these expressions to retrieve the corresponding data values. During this stage, the BML may appear as invalid XML due to the inclusion of BizzStream expressions, which are not standard XML elements. The focus here is on evaluating and resolving these expressions to prepare the dynamic content for display.

  2. Visually rendering the content: Once the BizzStream expressions have been resolved, the BML must conform to valid XML standards for the visual rendering process. This stage involves rendering the markup with actual data replacing the expressions, ensuring proper placement, styling, and presentation of all elements, including the dynamically obtained content.

Iterating line blocks with #EACH

Because BML's expression stage is resolved as a text expression, it supports more than a single inline {{ expression }} value - it also supports text expression blocks, such as {{#IF}}...{{/IF}} and {{#EACH}}...{{/EACH}}.

#EACH iterates over a collection and repeats the BML in between the opening and closing tag once per item. This makes it possible to render the contents of a line block read-only, directly with BML controls, as an alternative to showing a grid. To iterate a line block, point #EACH at the whole line collection using L["lineName"][*]:

<bml>
  {{#EACH(L["lines"][*])}}
  <block display="flex" direction="horizontal" marginTop="4">
    <text width="70%">{{F["description"]}}</text>
    <text width="30%" alignHorizontally="right">{{FORMAT(F["amount"], "0.00")}}</text>
  </block>
  {{/EACH}}
</bml>

Inside the loop, F["fieldName"] refers to the current line's fields, not the parent document's fields, so {{F["description"]}} and {{F["amount"]}} above read from the line that is currently being rendered. #EACH can be nested to render nested line blocks, and can be combined with {{#IF}} inside the loop for per-line conditional rendering.

Sorting the lines

Line order inside a #EACH block follows the underlying data, not any grid sort configuration. To control the order, wrap the pointer in the SORT array operator:

<bml>
  {{#EACH(SORT(L["lines"][*], [["amount", "desc"]]))}}
  <block display="flex" direction="horizontal" marginTop="4">
    <text width="70%">{{F["description"]}}</text>
    <text width="30%" alignHorizontally="right">{{FORMAT(F["amount"], "0.00")}}</text>
  </block>
  {{/EACH}}
</bml>

This renders the lines ordered by amount in descending order, highest first.

Filtering the lines

To only render lines that meet a condition, wrap the pointer in the FILTERARRAY array operator instead. Inside the condition, use SRL (source-relative line) to point at the line currently being evaluated:

<bml>
  {{#EACH(FILTERARRAY(L["lines"][*], SRL.F["active"] = true))}}
  <text>{{F["description"]}}</text>
  {{/EACH}}
</bml>

SORT and FILTERARRAY can also be combined, for example FILTERARRAY(SORT(L["lines"][*], [["amount", "desc"]]), SRL.F["active"] = true), to render only the active lines, sorted by amount.

#EACH works identically in BML and in templates - both are resolved as text expressions.

Comments

BML supports standard XML comments, using the <!-- --> syntax. Comments can be placed anywhere between elements - including before the root <bml> tag - and are not part of the rendered output.

<bml>
    <!-- This block shows the employee's welcome message -->
    <text>Welcome {{F["employeeName"]}}!</text>
</bml>

Comments cannot be placed inside the content of a leaf element (such as <text>, <qr>, or <progress>), since their content is rendered as-is.

Preview

When using the BML code editor, the preview window on the right side of the screen provides a live representation of the component, reflecting exactly how it will appear in the final layout. This feature allows you to quickly visualize the code and make adjustments in real time. In addition to serving as a layout preview, the window also acts as an error checker.

If an issue is present in the code, the preview will highlight the location of the error and provide information about its type. While it may not always offer a specific solution, the preview window gives a clear indication of where the problem lies, helping you pinpoint and resolve issues more efficiently.