Identifiers and scoping

The Mobilengine form language features naming scopes with nesting. A scope is where an element in the form is accessible for data-binding. The outermost or global scope is accessible for data-binding anywhere in the form.

Global scope is defined implicitly by the framework and holds the root of the form with the id of the form, the built-in sysp scope for all the system parameters, and the reference tables.

You can declare any number of further scopes in the form by specifying an id field on a control. Controls that have an id begin their own scopes, which are nested in the scope of their closest ancestor with an identifier.

...
<textview label="Reference to a property in the nested scope"
  text='{parent-scope.nested-scope.label}'/>
<chapter id="parent-scope"
  title="Closest named ancestor">
  <popup id="nested-scope"
    label="FIZZBUNGLE"
    title="Popup title">
    <textview text='{nested-scope.label}'/>
  </popup>
</chapter>
In references from outside the parent scope, a property's qualified name includes both the parent and the nested scope

Figure 217. In references from outside the parent scope, a property's qualified name includes both the parent and the nested scope


If a named control has no ancestor with an identifier, its scope will be nested in the form root.

<form id="scopes"...>
...
  <textview label="The text input from inside the popup:"
    text='{scopes.boxBar.text}'/>
  <popup title="Reference to a named control from an aunt">
    <textbox id="boxBar"
      label="Type something"/>
    <textview label="Your text input appears here"
      text='{boxBar.text}'/>
  </popup>
...
</form>
The boxBar textbox has no named ancestor: it is accessible in the global scope

Figure 218. The boxBar textbox has no named ancestor: it is accessible in the global scope


Generally, control properties and variables are accessible for data-binding only if they have an id field declared. The single exception is that a control's own properties are accessible for data-binding in other properties of the control.

...
<textview label="Walla" text='{UPPER(label)}'/>
...
The label property of the textview is accessible inside it even though it doesn't have an id field

Figure 219. The label property of the textview is accessible inside it even though it doesn't have an id field


Properties and variables are accessible within their own and all their nested scopes by using their unprefixed names. From within external scopes, you need to use qualified names to access them.

...
<textview label="The text input from inside the popup"
  text='{popBaz.boxYolo.text}'/>
<popup id="popBaz"
  title="Reference to a named control in a named parent">
  <textbox id="boxYolo"
    label="Type something"/>
</popup>
...
The textview references a child control inside the named popup

Figure 220. The textview references a child control inside the named popup


Identifiers must be unique within their scope.

<!-- This control declaration would throw an error
<chapter title="The same id declared in the same
              (in this case, the global) scope">
  <textbox id='search'/>
  <textbox id='search'/>
</chapter>
-->

However, in a nested scope, you can have controls or variables with identifiers that shadow an identifier in the parent scope.

...
<popup id='knights'
  title='Ni no more'>
  <textbox id='ni'
    width="30 em"
    text='We are no longer
        the knights who say ni.'/>
</popup>
<popup id='newKnights'
  title='Ekki-ekki-ekki-pitang-zoom-boing'>
  <textbox id='ni'
    width="40 em"
    text='We are the knights who say
      ekki-ekki-ekki-pitang-zoom-boing.'/>
</popup>

If you declare an element in a nested scope with an identifier that already exists in a parent scope, the same-named identifier will shadow the parent's one inside the nested scope, that is, refer to the newly-created element.

You have to use qualified names to access the shadowed properties inside the nested scope where the shadowing identifier is declared, to make sure that you don't return the value of the masking property instead of the shadowed one.

...
<chapter id="parent"
  title="Parent scope">
  <textbox id="tbFoo"
    text="parent-value"/>
  <chapter id="nested"
    title="Nested scope">
    <textbox id="tbFoo"
      text="nested-value"/>
    <textview label="tbFoo.text"
      text='{tbFoo.text}'/>
    <textview label="parent.tbFoo.text"
      text='{parent.tbFoo.text}'/>
  </chapter>
  <textview label="tbFoo.text"
    text='{tbFoo.text}'/>
</chapter>
...
Reference to the same identifier returns different results depending on the current scope

Figure 221. Reference to the same identifier returns different results depending on the current scope


The names of reference table names may not be shadowed by any identifier in a form.

<!-- This would throw an
'Ambiguous name:...' error message
at compile time
<textbox id="passenger"
  text="This is invisible ink."/>
<textview text='{SELECT l.first_name
                FROM passenger l}'/>
    -->