In this lesson, we will talk about scopes and references. These will help you make rules and actions reusable and also access and manage data throughout your component.

There are two scopes in which you can declare rules, actions, and store data:

  • step: Each step of a component has its own scope. Rules, actions, and data defined here are not available elsewhere.
  • workflow: All steps of a component have access to the rules, actions, and data added to the workflow scope.

Additionally, there are three scopes available to store data:

  • root: All components of a workflow have access to the root scope. This can be used to pass data between components.
  • user_session: As long as the user does not log out, data stored in the user_session scope will be accessible even after finishing the workflow execution (e.g., from inside another workflow or when executing the same workflow multiple times).
  • global: As long as the Frontline Workplace application is not closed, data stored in the global scope will be accessible, even if a user signs out and another user signs in.

Example Component

<workflow [ATTRIBUTES]>
    <context> [...] </context>                              \
    <actions> [...] </actions>                              -\
    <rules>                                                 --\ 
        <rule id="menu_button_selection">                   ---\
            <expression>[..]</expression>                   ----\
            <actions>                                       -----|--> Workflow scope
                [...]                                       ----/
            </actions>                                      ---/
        </rule>                                             --/
    </rules>                                                -/
                               
    <steps> 
        <step id="stepA" [ATTRIBUTES]>
            <context> [...] </context>                      ----\
            <rules> [...] </rules>                          -----|--> Step scope
            <actions> [...] </actions>                      ----/
            <states>
                <onevent> 
                    <rule ref="menu_button_selection"/>     -------> Referencing a rule from the workflow scope

                    <rule id="show_notification">           --\
                        <expression>[..]</expression>       ---\
                        <actions>                           ----\
                            [...]                           -----|--> Direct definition (could still reference a pre-defined action)
                        </actions>                          ----/
                    </rule>                                 ---/
                </onevent> 
            </states>
        </step>

        <step id="stepB" [ATTRIBUTES]>
            <states>
                <onevent> 
                    <rule ref="menu_button_selection"/>     -------> Referencing a rule from the workflow scope
                </onevent> 
            </states>
        </step>
    </steps>
</workflow>

In this example:

  • A rule with id="menu_button_selection" is defined in the workflow scope and then referenced in both step id="stepA" and step id="stepB" using the ref attribute.

Note: Reusing rules and actions makes the behavior of your component consistent, improves maintainability, and minimizes the amount of code.

  • IDs inside a scope have to be unique. You can use identical IDs in other scopes, but unless you have a very good reason we recommend not doing so, to prevent confusion. If you use identical IDs, the order of precedence is bottom-up: if a rule with id="menu_button_selection" is directly defined in the step scope it will be executed instead of any pre-defined rules with the same ID in the workflow scope.
  • You might also have rules/actions that are only needed in one of your steps but are needed in multiple states/rules of that particular step. In this case, you can define the rule/action in the step scope and reference it in the same way.
  • Finally, you can also define rules and actions directly where they are needed. Such a rule/action will not be available anywhere else. If you know your rule/action will not be re-used, a direct definition can make the component more legible since you don't have to jump around to see the implementation.

Note: IDs have to be unique within a scope. If you copy & paste an existing rule or action as a template when creating a new one, a typical mistake is forgetting to change the ID attribute. Make it a habit to change the ID first.

📌Assignment

Refactor our choice component:

  • Put the finish_workflow action into the global scope and reference it in the rule
  • Put the menu_button_selection rule into the global scope and reference it in the step
  • Make sure the component still works as intended

 Download Component (Pre-Assignment)

Help and Resources

Here are a few tips to make developing workflows and components a bit easier:

Preview mode

This mode allows you to immediately test your changes without having to publish the workflow. For more information, see the Preview Workflow section.

Server and Client Logs

You can access the FCC and device logs by logging in with the sysadmin user or by directly accessing your UBIMAX_HOME\logs folder. The device logs are pushed to the server periodically, but you can request immediate upload as a sysadmin user.

Solution Notes

If you did not have everything set up for development yet, that should have been the major task for this first practical assignment.

It might be noteworthy, that in the rule definition, you now reference a pre-defined action defined in the same scope. The order of the <actions>and <rules> tags do not matter for this to work. Here is what your component should look like:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<workflow xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" wfd_version="1.0" reporting="false"
          id="choice" name="choice" descriptor="Choice component" startstep="choose"
          xsi:noNamespaceSchemaLocation="../../../configuration/workflow.xsd">
   
    <actions>
        <finish_workflow id="finish_workflow"> 
            <output>
                <param name="selected_button" type="string">#{event:command}</param>
            </output>
        </finish_workflow>
    </actions>
   

    <rules>
        <rule id="menu_button_selection">
            <expression>#{event:command} == 'APPLE' || #{event:command} == 'PEAR'</expression>
            <actions>
                <action ref="finish_workflow"/>
            </actions>
        </rule>  
    </rules>

 

    <steps>
        <step id="choose" descriptor="the user selects between two options" uitemplate="ChoiceScreen">
            <states>
                <onevent>
                    <rule ref="menu_button_selection"/>
                </onevent>
            </states>
        </step>
    </steps>

</workflow>

Download Component (Post-Assignment)

With this, you have finished the second lesson. The next lesson will be about data variables.