Markup

This section details the XMLUI markup fundamentals. The markup is almost identical to the XML/XHTML; there are only a few points where XMLUI extends them.

Comments

💡

XMLUI comments use the same syntax as XML/XHTML comments.

<!-- This is an XMLUI comment, it could be an XML or XHTML comment, too -->
💡

XMLUI allows you to use comments within tags.

<Button <!-- This is a comment --> label="Click me!" />

XML and XHTML does not allow comments within an element. However, XMLUI does; you can place comments before and after attributes or before an element's closing > or \> tag. This feature is helpful for the temporary removal of a particular attribute (wrapped within a comment) during development.

Tags

💡

XML uses tags for components and helper tags.

  • Each component tag represents a particular tag in the app's component hierarchy. These tags use an identifier starting with an uppercase letter.
  • Tags starting with a lowercase letter are helper tags. Each helper tag has a particular role, and the engine transforms them accordingly.
<!-- Simple tag without nested children -->
<Button label="Click Me!" />
 
<!-- With separate opening and closing tags -->
<Button label="Click Me!"></Button>
 
<!-- With child items -->
<VStack>
  <Text>Welcome</Text>
  <Button label="Click Me!" />
</VStack>
📔

XMLUI tag names start with a letter and may be continued with letters, digits, and these characters: dash (-), underscore (_), dollar sign ($), and dot (.).

In the following code, <property> is a helper tag. XMLUI uses the <property> helper to specify the value of a property, which cannot be represented as a string.

<DropdownMenu>
  <property name="triggerTemplate">
    <Button label="My Menu" icon="chevrondown" iconPosition="right"/>
  </property>
  <MenuItem>Item 1</MenuItem>
  <MenuItem>Item 2</MenuItem>
  <MenuItem>Item 3</MenuItem>
</DropdownMenu>

The order of component tags reflects their display order. However, the order of helper tags embedded into other tags is invariant; they can have any order and still resulting the same effect. So, the following markup renders the same UI as the previous one:

<DropdownMenu>
  <MenuItem>Item 1</MenuItem>
  <MenuItem>Item 2</MenuItem>
  <MenuItem>Item 3</MenuItem>
  <property name="triggerTemplate">
    <Button label="My Menu" icon="chevrondown" iconPosition="right"/>
  </property>
</DropdownMenu>

Tag Namespaces

💡

XMLUI reserves namespaces for future extensions. When you use them, the framework simply ignores them.

<myPackage:Button label="Click me!" />

This declaration renders a Button as if you used it without a namespace.

⚠️

Using different namespace prefixes in an opening and the related closing tag is considered an error.

The following markup would not compile:

<some:Text>
  This is wrong.
</other:Text>

Attributes

💡

XMLUI attributes have the same role as HTML attributes; they define a particular component trait (e.g., property, event handler, etc.) or a helper tag's attribute.

Attribute names start with a letter and may be continued with letters, digits, and these characters: dash (-), underscore (_), dollar sign ($), and dot (.). By convention, attributes should always begin with a lowercase letter.

📔

XMLUI attribute values may use three types of wrapper characters: single quotes ('), double quotes ("), or backtick (`). The starting and closing delimiter should be the same, so, for example, you cannot start an attribute value with a backtick and close it with a double quote.

In the following code snippet, all attribute values are accepted:

<Button label='Click Me!' color="#a0a0a0" width=`50%` padding=".2rem" />

Multi-Line Attribute Values

💡

Unlike in XML and XHTML, XMLUI allows you to break an attribute's value into multiple lines (assuming you use delimiter quotes). The engine preserves all whitespaces between the delimiters, including spaces, tabs, and line breaks; those characters are part of the attribute value.

In the following code snippet, the onClick attribute of <Button> contains three line breaks (one before isRunning, one before while, and a third one after count++;):

<Button label="Infinite loop: {count}" onClick="
  isRunning = true;
  while (isRunning) count++;
" />

Key-Only Attributes

💡

You can use attributes without a value. XMLUI considers them as attributes with the value of "true". These key-only attributes help represent the turned-on state of particular component properties.

For example, you could use this markup to sign an active menu item:

<MenuItem label="Open" active="true" />

With key-only attributes, you can make this markup more concise:

<MenuItem label="Open" active />

Quoteless Attributes

💡

You can omit quotes when defining an attribute value, provided the value does not contain whitespaces and its characters are letters, numbers, and one of these characters: dot (.), dash (-), underscore (_), and dollar sign ($).

The following Text component's value is an expression that matches the "quoteless" criterium:

<Text value="re-fetch" />

Thus, you can omit the double quotes when defining it:

<Text value=re-fetch />

Entity References

💡

In XMLUI text and attribute values, you do not need to use entity references (such as &amp;, &gt;, and others. However, you may use them, and the XMLUI parser will understand them.

  • &amp;: & (ampersand)
  • &gt;: > (greater than)
  • &lt;: < (less than)
  • &apos;: ' (apostrophe)
  • &quot;: " (double quote)
  • &nbsp;: non-breaking space

So, each of these text pairs represents the same text:

<Text>You're so beautiful</Text>
<Text>You&apos;re so beautiful</Text>
 
<Text>"Hello", she said</Text>
<Text>&quot;Hello&quot;, she said</Text>
 
<Text>"2 < 3"</Text>
<Text>2 &lt; 3</Text>
 
<Text>Go to --> Step #3</Text>
<Text>Go to --&gt; Step #3</Text>
 
<Text>Mac & Jack</Text>
<Text>Mac &amp; Jack</Text>
 
<Text>Keep&nbsp;going</Text>
<Text>Keep{"\\xa0"}going</Text>

This markup will output the following:

Nesting Child Items

💡

In the markup, you can nest child items into any component. Each of these children can be a tag or a text value.

<VStack>
  This is a text segment before a Button component.
  <Button label="I'm a non-functional Button"/>
  This is a text segment after a Button and before an Icon
  <Icon name="user" />
</VStack>

Tag Text Values

💡

Unlike attribute values, tag text values do not preserve whitespaces; they use the same whitespace collapsing that HTML applies. The engine removes extra spaces, tabs, and line breaks:

<Text>
  Though      this is a multiline text     declaration (with several line breaks),
  the engine        collapses whitespaces.
 
</Text>

The engine will display the following text after collapsing whitespaces:

📔

There are several characters you have to handle with care. The left angle ( < ) is a delimiter character used as the start character of an opening XMLUI tag. If you want to display it, wrap the text into quotes.

<Text>
  "I'm a text containing a left angle: <"
</Text>

You can use double quotes ("), single quotes ('), or backticks (`) as wrappers; the starting and ending characters should be the same.

CDATA section

💡

The CDATA section (using the same syntax as in XML) ensures that text value within an XMLUI tag preserves all characters (prevents whitespace collapsing).

<MarkDown>
  <![CDATA[
# Who's that then?
 
Well, she turned me into a newt. Burn her! We want a shrubbery!! Well, I got better.
Listen. __Strange women lying in ponds distributing swords is no basis for a system of
government.__ *Supreme executive power derives from a mandate from the masses, not from
some farcical aquatic ceremony.* The swallow may fly south with the sun, and the house
martin or the plover may seek warmer climes in winter, yet these are not strangers to our
land.
 
## Well, Mercia's a temperate zone!
 
You don't frighten us, English pig-dogs! Go and boil your bottoms, sons of a silly person!
I blow my nose at you, so-called Ah-thoor Keeng, you and all your silly English
K-n-n-n-n-n-n-n-niggits! A newt?
  ]]>
</Markdown>

This sample uses the Markdown components where whitespaces are essential to display the desired text format.

Child Hierarchy

💡
<HStack>
  <VStack width="25%">
    This is Button #1!
    <Button label="Button #1" />
  </VStack>
  <VStack width="25%">
    This is Button #2!
    <Button label="Button #2" />
  </VStack>
  <VStack width="25%">
    Three Boxes
    <HStack>
      <Stack backgroundColor="red" width="36" height="36" />
      <Stack backgroundColor="green" width="36" height="36" />
      <Stack backgroundColor="blue" width="36" height="36" />
    </HStack>
  </VStack>
</HStack>

Declaring Apps

💡

When you describe an app, you use the XMLUI markup to declare an app or a reusable component. Whether you define an app or a component, your definition must have a single root tag.

<App>
  <!-- You can nest child components into this slot -->
</App>
📔

Recall that component names start with uppercase letters.

The engine raises an error if the app or component markup contains multiple root tags:

<!-- This markup is not valid -->
<Button label="Click me!" />
<Text>Clicked!</Text>
💡

If you do not have a better solution, you can enclose multiple tags into a <Fragment> tag. This tag does not add any visual or functional overhear to your app.

<!-- Now, this markup is valid -->
<Fragment>
  <Button label="Click me!"/>
  <Text>Clicked!</Text>
</Fragment>

Properties

💡

XMLUI uses markup attributes to represent component properties. Attributes have the same name as the particular property.

<Button label="Click me!"/>
💡

When properties cannot be represented with a string, you nest them into their related component with the <property> tag. Use the tag's name attribute to identify the property.

<DropdownMenu>
  <property name="triggerTemplate">
    <Button label="My Menu" icon="chevrondown" iconPosition="right"/>
  </property>
  <MenuItem>Item 1</MenuItem>
  <MenuItem>Item 2</MenuItem>
  <MenuItem>Item 3</MenuItem>
</DropdownMenu>

triggerTemplate is a property of the DropdownMenu component that defines the UI for the trigger that opens the dropdown menu.

💡

If you prefer explicitly using the <property> tag, you can use it to represent string data; specify that with the value attribute.

<Button>
  <property name="label" value="Click me!"/>
</Button>
💡

You can use the <property> tag with nested text as an alternative to the value attribute.

Event Handlers

💡

You can use the event tag to define event handlers for these situations:

Connect Button click to APICall

<Button label="Change Name">
  <event name="click">
    <APICall
      url="/api/shopping-list-slow/{$item.id}"
      method="put"
      body="{{ name: itemName.value }}"
      inProgressNotificationMessage="Name change pending..."
      completedNotificationMessage="Name change successful!"
    />
  </event>
</Button>

Connect MenuItem click to APICall

<MenuItem label="Delete">
  <event name="click">
    <APICall
      url="/api/contacts/{$item.id}"
      method="delete"
      confirmTitle="Delete Contact {$item.fullName}"
      confirmMessage="Are you sure you want to delete this contact?"
      confirmButtonLabel="Delete" />
  </event>
</MenuItem>

Connect Form submit to APICall

<Form data="{{ age: 43 }}">
  <event name="submit">
    <APICall
      url="/api/contacts/age"
      method="POST"
      body="{$param}" />
  </event>
  <FlowLayout>
    <H3>Customer Age</H3>
    <FormItem bindTo="age" label="Age" type="integer" zeroOrPositive="true" />
  </FlowLayout>
</Form>

Connect Checkbox change to APICall

<Column header = "fave">
  <Checkbox initialValue="{$item.fave}">
    <event name="didChange">
      <APICall
        method="post"
        url="{ window.xmluiHost + '/query' }"
        body="{ window.favorite($item.id, $item.fave ? 0 : 1) }"
        />
    </event>
  </Checkbox>
</Column>

Variable declarations

💡

Besides code-behind files, you can use inline variable declarations in the markup. The most concise way is to use an attribute with the var. prefix followed by the variable's name.

<Button label="Click me!" var.greeting="Hello!"/>

This markup assigns a variable named greeting to the Button with the initial value of "Hello!".

💡

You may prefer more explicit variable declarations. You can do it with the var tag, too.

<Button label="Click me!">
  <variable name="greeting" value="Hello!">
</Button>

And similarly to <property>, XMLUI accepts nested text for the variable's initial value.

<Button label="Click me!">
  <variable name="greeting">Hello!</variable>
</Button>
💡

The type of a variable's value is significant when working with code. When you initialize variables, their value is a string (as tag attributes are strings). If you want to be sure a variable value is initialized with the intended type, use binding expressions.

<!-- count is a string, "0" -->
<Button label="Click me!">
  <variable name="count" value="0"/>
</Button>
 
<!-- count is a number, 0 -->
<Button label="Click me!">
  <variable name="count" value="{0}"/>
</Button>
 
<!-- isOpen is a string, "true" -->
<Button label="Click me!">
  <variable name="isOpen" value="true"/>
</Button>
 
<!-- isOpen is a boolean, true -->
<Button label="Click me!" var.isOpen="{true}"/>
📔

Components are smart enough to convert the string values of properties to the appropriate type they expect.

💡

You can use a binding expression to define a compound value.

<Fragment>
  <variable name="origin" value="{{x: 100, y: 40}}"/>
</Fragment>

In the {{x: 100, y: 40}} binding expression, the outer curly braces are the delimiters; the {x: 100, y: 40} object literal defines a hash object with x and y properties.

Reusable Components

💡

You can define reusable components with the <Component> tag. These declarations should go into a separate file within the app's components folder. Use the name attribute to assign a unique name to the component.

<Component name="IncButton">
  <variable name="count" value="{0}"/>
  <Button label="Click to increment: {count}" onClick="count++"/>
</Component>
📔

The name attribute of the component should start with an uppercase letter.

You can add the new component to your app with the <IncButton> tag.

<App>
  <!-- Other components -->
  <IncButton/>
</App>
💡

Reusable components can expose custom methods from a particular component.

To declare them, you can use two notations (according to your preference):

With method. prefix:

<Component
  name="IncButton"
  var.count="{0}"
  method.setValue="v => count = v">
  <Button label="Click to increment: {count}" onClick="count++"/>
</Component>

With the <method> tag:

<Component name="IncButton"
  <variable name="count" value="{0}"/>
  <method name="setValue" value="v => count = v"/>
  <Button label="Click to increment: {count}" onClick="count++"/>
</Component>

These two notations are equivalent.