Local Variables

This page is an overview of what local variables are and how to use them.

For a detailed description of how to use a!localVariables relative to the load and with functions, see Updating Expressions to Use a!localVariables.

Overview

Variables store data that can be used when evaluating an expression. Local variables are a specific type of variable that are only available within the context of a particular expression and can only be accessed within the function that defines them.

Local variables are useful when you only need that data within a particular expression. For example, if you need to reuse a calculated value in multiple places within a single expression, you can store that in a local variable. Additionally, if you need to store a user input that doesn't need to be stored elsewhere, such as a search term, you can also use a local variable for that.

Defining Local Variables

Local variables are defined in the a!localVariables function. You can define both the name and the value of the local variable, then use those variables in the last parameter of the function:

1
2
3
4
5
a!localVariables(
  local!a: 1,
  local!b: 2,
  local!a + local!b
)

Variables may also be defined without an initial value. This is most commonly used when the variable is intended to store a user's input that doesn't have a default value.

1
2
3
4
5
6
7
8
a!localVariables(
  local!input,
  a!textField(
    label: "Input",
    value: local!input,
    saveInto: local!input
  )
)

All local variables must be defined within the local! domain and must have a unique name within that same function.

Referencing Other Variables

When defining the value of a local variable, you may use other types of variables. This includes process variables, rule inputs, and other local variables that were previously defined.

1
2
3
4
5
a!localVariables(
  local!record: rule!getRecordForId(ri!id),
  local!attachments: folder(local!record.folderId, "documentChildren"),
  rule!displayAttachments(local!attachments)
)

Referencing another local variable creates a dependency between the two variables and ensures that the referenced variable is always evaluated first. All variables that are independent of each other may be evaluated in parallel, while variables that depend on each other are always sequentially evaluated.

Using Local Variables

Once a local variable is defined, it can be used only within the function that defined it. It can be used both in the definition of other local variables defined after it or within the expression parameter. It can be used inside any number of functions within the expression parameter, no matter how deeply nested they are. However, it cannot be used directly within another rule, as described below.

Appian recommends always using the local! domain when using a local variable to reduce ambiguity both when reading the expression and when evaluating the expression.

Nesting a!localVariables

When you use a!localVariables inside another a!localVariables, you can reference local variables created in the parent function.

1
2
3
4
5
6
7
8
9
10
11
12
a!localVariables(
  local!cases: rule!getAllCases(),
  local!drilldownId,
  if(
    isnull(local!drilldownId),
    rule!displayCasesSection(local!cases),
    a!localVariables(
      local!case: rule!getCaseById(local!drilldownId),
      rule!displayCaseSection(local!case)
    )
  ) 
)

In this example, local!case can reference local!drilldownId because they are defined within the same expression and local!drilldownId is still being used inside the expression parameter.

Local Variables in Other Parts of the Expression

Variables defined in a totally different part of the expression cannot be referenced. Doing so will result in an error.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
a!columnsLayout(
  columns: {
    a!columnLayout(
      contents: {
        a!localVariables(
          local!input,
          a!textField(
            label: "Input",
            value: local!input,
            saveInto: local!input
          )
        )
      }
    ),
    a!columnLayout(
      contents: {
        a!textField(
          label: "Input Entered?",
          value: if(isnull(local!input), "No", "Yes"),
          readOnly: true
        )
      }
    )
  }
)

In this example, the Input Entered field cannot reference local!input because it isn't within the expression parameter of the a!localVariables where local!input was defined. Only the Input field has access to local!input.

If you need to access the same variable in multiple parts of your expression, be sure to define that variable early enough so that each location can access it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
a!columnsLayout(
  columns: {
    a!localVariables(
      local!input,
      {
        a!columnLayout(
          contents: {
            a!textField(
              label: "Input",
              value: local!input,
              saveInto: local!input
            )
          }
        ),
        a!columnLayout(
          contents: {
            a!textField(
              label: "Input Entered?",
              value: if(isnull(local!input), "No", "Yes"),
              readOnly: true
            )
          }
        )
      }
    )
  }
)

In this case, the local!input would need to be defined at least at the columns parameter of a!columnsLayout so that both components could access it, though it is more common to define these types of variables at the top of the expression.

Local Variables in Other Rules

Local variables created in other rules cannot be used.

Say in the following example you wanted to reference local!drilldownId within rule!DisplayCaseSection() in order to query the case.

1
2
3
4
5
6
7
8
9
a!localVariables(
  local!cases: rule!getAllCases(),
  local!drilldownId,
  if(
    isnull(local!drilldownId),
    rule!displayCasesSection(local!cases),
    rule!displayCaseSection()
  ) 
)

rule!displayCaseSection() cannot reference local!drilldownId directly because it wasn't defined within that rule. Instead, you should create a rule input and pass local!drilldownId in, as shown below.

1
2
3
4
5
6
7
8
9
a!localVariables(
  local!cases: rule!getAllCases(),
  local!drilldownId,
  if(
    isnull(local!drilldownId),
    rule!displayCasesSection(cases: local!cases),
    rule!displayCaseSection(caseId: local!drilldownId)
  ) 
)

Local Variables With the Same Name

While local variables within the same function must have unique names, it is possible to create local variables with the same name in different parts of the expression. When this occurs, the variable defined the innermost variable of that name will be used.

1
2
3
4
5
6
7
8
9
a!localVariables(
  local!var1: 1,
  a!localVariables(
    local!var2: local!var1 + 1,
    local!var1: 10,
    local!var3: local!var1 + 1,
    local!var3
  )
)

In this example, local!var2 uses the original value for local!var1 and therefore is 2. However, local!var3 uses the new value for local!var1 as defined in the lower scope and therefore is 11. As this can often cause confusion, it is not recommended to use the same local variable names within the same interface.

Local Variable Types

Local variables do not have a defined type. The type of a local variable is determined by the value of the variable at any given time.

1
2
3
4
5
6
7
8
9
10
11
a!localVariables(
  local!isActive: true,
  local!activeEmployees: a!queryEntity(
    entity: cons!EMPLOYEE_DSE,
    query: a!query(
      filter: a!queryFilter("active", "=", local!isActive),
      pagingInfo: a!pagingInfo(1, 10)
    )
  ).data,
  local!activeEmployees
)

In this example, local!isActive is of type Boolean and local!activeEmployees is of type Dictionary.

Variables Without an Initial Value

Local variables that do not have an initial value are of type Null. This can often cause errors when trying to pass the local variable to a function, so you may need to cast it to the expected type.

1
2
3
4
5
6
7
8
9
10
11
12
13
a!localVariables(
  local!quantity,
  a!integerField(
    label: "Quantity",
    value: local!quantity,
    saveInto: local!quantity,
    validations: if(
      local!quantity<0,
      "Quantity must be greater than 0",
      ""
    )
  )
)

In this example, local!quantity<0 fails because the variable is not an integer. You can solve this by casting the variable before doing comparisons using the tointeger() function.

Updating a Variable Value

The type of a local variable can change if it is saved into from a component within an interface. The variable will now be of the same type as the new value that was saved into it.

1
2
3
4
5
6
7
8
a!localVariables(
  local!number: 1,
  a!floatingPointField(
    label: "Number",
    value: local!number,
    saveInto: local!number
  )
)

In this example, local!number starts out as an Integer. However, once a user interacts with the Number field, a Decimal value will be saved into local!number.

Configuring Refresh Behavior

Local variables that are used within interfaces can refresh their values under a variety of conditions. When a variable is refreshed, the value of that variable is recalculated and the variable is updated with the latest value.

By default, all variables defined within a!localVariables refresh when a variable that is referenced in the value configuration changes. You can change these refresh behaviors using the a!refreshVariable function. These configurations are only available within an interface; they are ignored when used in an expression outside of an interface.

This table contains a summary of each refresh configuration, which is described in further details in the sections below:

Refresh Behavior a!refreshVariable configuration Valid Save Target?
Never refresh because variable has no dependencies None (default behavior)
Never refresh even when dependencies change refreshOnReferencedVarChange: false
Refresh when any referenced variable changes None (default behavior)
Refresh when a specific variable changes refreshOnVarChange: {local!var}
Refresh on a timer refreshInterval: 1
Refresh after every user interaction refreshAlways: true

Never Refresh

By default, variables with no dependencies will never refresh, even without using a!refreshVariable to disable it.

1
2
3
4
5
6
7
8
9
10
a!localVariables(
  local!comment,
  local!commenter: loggedInUser(),
  local!commentDate: today(),
  a!paragraphField(
    label: "Comments",
    value: local!comment,
    saveInto: local!comment
  )
)

In the example above, none of the local variables will ever be refreshed because their values do not depend on other variables.

However, local variables that depend on other variables will be refreshed automatically when those dependencies are updated. To disable that behavior, see Disabling Refresh When Referenced Variables Change.

Refresh When Referenced Variables Change

Any variable defined without using a!refreshVariable will automatically refresh its value when any variable it depends on changes. Additionally, the value will not be refreshed until something it depends on changes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
a!localVariables(
  local!checkIn: today(),
  local!checkOutDate: local!checkIn+1,
  local!checkOutTime: if(weekday(local!checkOutDate, 2)<6, time(11, 0, 0), time(12, 0, 0)),
  local!numOfRooms: 1,
  {
    a!dateField(
      label: "Check in",
      value: local!checkIn,
      saveInto: local!checkIn
    ),
    a!dateField(
      label: "Check out",
      value: local!checkOutDate,
      saveInto: local!checkOutDate,
      instructions: "Check out time is at " & local!checkOutTime
    ),
    a!integerField(
      label: "Number of Rooms",
      value: local!numOfRooms,
      saveInto: local!numOfRooms
    )
  }
)

In this example, the local variables have the following refresh behaviors:

  • local!checkIn and local!numOfRooms will never be refreshed because they do not depend on any other variables
  • When the value of local!checkIn changes, both local!checkOutDate and local!checkOutTime will be refreshed; local!checkOutDate because it depends on local!checkIn and local!checkOutTime because it depends on local!checkOutDate
  • local!checkOutTime will also be refreshed when local!checkOutDate is updated by interacting with the Check out date field

Referencing Specific Fields Within a Variable

Variables that depend on a specific field within another variable (e.g. local variables, rule inputs, etc.) will only refresh when that field is updated, rather than the entire variable.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
a!localVariables(
  local!departments: rule!getAllDepartments(),
  local!titles: rule!getTitlesByDepartment(ri!employee.department),
  {
    a!textField(
      label: "Name",
      value: ri!employee.name,
      saveInto: ri!employee.name
    ),
    a!dropdownField(
      label: "Departments",
      placeholderLabel: "Select a department",
      choiceLabels: local!departments,
      choiceValues: local!departments,
      value: ri!employee.department,
      saveInto: ri!employee.department
    ),
    a!dropdownField(
      label: "Titles",
      showWhen: not(isnull(ri!employee.department)),
      placeholderLabel: "Select a title",
      choiceLabels: local!titles,
      choiceValues: local!titles,
      value: ri!employee.title,
      saveInto: ri!employee.title
    )
  }
)

In this example, when either the name or title field of ri!employee changes, local!titles will not be queried again since ri!employee.department has not changed.

The same concept applies not only when using dot indexing, but also with bracket indexing. For example:

1
local!titles: rule!getTitlesByDepartment(ri!employee["department"])

In addition, this will also work for array indexing.

If you need to use the index function to provide a default value, then you need to place the index function in an intermediate local variable to achieve the same behavior. For our example, you could do the following:

1
2
local!department: index(ri!employee, "department", "None"),
local!titles: rule!getTitlesByDepartment(local!department),

While local!department depends on the entire value of ri!employee and will update whenever any field within it changes, local!titles will only update when the value of local!department changes. Since the value of local!department won't change unless the "department" field changes, the same effect is achieved.

What is Considered a "Referenced Variable"?

All variables are considered dependencies even if they are only used within a part of the expression that isn't evaluated.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
a!localVariables(
  local!countCharacters: false,
  local!text,
  local!textLength: if(
    local!countCharacters,
    len(local!text),
    ""
  ),
  {
    a!radioButtonField(
      label: "Count Characters",
      choiceLabels: {"Yes", "No"},
      choiceValues: {true, false},
      value: local!countCharacters,
      saveInto: local!countCharacters
    ),
    a!paragraphField(
      label: "Text",
      value: local!text,
      saveInto: local!text,
      instructions: if(isnull(local!textLength), "", local!textLength & " characters")
    )
  }
)

In this example, local!text is still considered a dependency of local!textLength, even when it's in a branch of the if() that doesn't get evaluated. Therefore, updating local!text will cause local!textLength to get refreshed automatically even when local!countCharacters is false.

Saving Into Variables With Dependencies

Even though these variables can be updated automatically, you can still save into them.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
a!localVariables(
  local!checkIn: today(),
  local!checkOut: local!checkIn+1,
  {
    a!dateField(
      label: "Check in",
      value: local!checkIn,
      saveInto: local!checkIn
    ),
    a!dateField(
      label: "Check out",
      value: local!checkOut,
      saveInto: local!checkOut
    )
  }
)

In this example, you can update the value of local!checkOut by interacting with the Check out field. However, when you interact with the Check in field, local!checkOut is refreshed and the value is overwritten.

Disabling Refresh When Referenced Variables Change

You may want to disable this behavior if you want to make a copy of a variable for later comparison or if you simply don't want something to be calculated each time a variable it depends on changes. To disable this feature, set the refreshOnReferencedVarChange parameter to false.

1
2
3
4
5
6
7
8
9
10
11
a!localVariables(
  local!original: 1,
  local!copy: a!refreshVariable(
    value: local!original,
    refreshOnReferencedVarChange: false
  ),
  {
    a!textField(label: "Original", value: local!original, saveInto: local!original),
    a!textField(label: "Copy", value: local!copy, saveInto: local!copy)
  }
)

In the example, updating local!original does not refresh the value of local!copy.

The refreshOnReferencedVarChange parameter is calculated every evaluation, even if the value of the variable is not. This is to enable you to dynamically change the refresh behavior as data changes within the interface.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
a!localVariables(
  local!checkIn: today(),
  local!checkOutEdited: false,
  local!checkOut: a!refreshVariable(
    value: local!checkIn+1,
    refreshOnReferencedVarChange: not(local!checkOutEdited)
  ),
  {
    a!dateField(
      label: "Check in",
      value: local!checkIn,
      saveInto: local!checkIn
    ),
    a!dateField(
      label: "Check out",
      value: local!checkOut,
      saveInto: {
        local!checkOut,
        a!save(local!checkOutEdited, true)
      }
    )
  }
)

In this example, local!checkOut starts out by refreshing automatically each time local!checkIn is updated. However, when you update the value of local!checkOutEdited to be true, local!checkOut no longer updates when local!checkIn changes.

Refresh When Specific Variables Change

If you need a variable to refresh when a variable it doesn't directly depend on changes, you can use the refreshOnVarChange parameter. Simply define one or more variables that this variable indirectly depends on to automatically update it when one of them changes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
a!localVariables(
  local!name: "John Smith",
  local!username: "john.smith",
  local!usernameEditedTimestamp: a!refreshVariable(
    value: now(),
    refreshOnVarChange: local!username
  ),
  {
    a!textField(
      label: "Name",
      value: local!name,
      saveInto: local!name
    ),
    a!textField(
      label: "Username",
      value: local!username,
      saveInto: local!username
    ),
    a!dateTimeField(
      label: "Username Last Edited",
      value: local!usernameEditedTimestamp,
      readOnly: true
    )
  }
)

In this example, local!usernameEditedTimestamp will be updated each time you change local!username even though its value doesn't directly depend on it. However, local!usernameEditedTimestamp won't be updated when you change local!name.

The refreshOnVarChange parameter can only be defined as a single variable (refreshOnVarChange: local!var1) or a list of variables (refreshOnVarChange: {local!var1, local!var2}). It may not be dynamically calculated using any rules or functions. For example, it cannot be defined as if([some condition], local!a, local!b).

Refresh Interval

If you need a variable to refresh periodically on a time-based interval, you can use the refreshInterval parameter. This will allow your data to get refreshed even when the user doesn't interact with the interface.

You cannot save into variables that are configured to refresh on an interval.

Conditionally Enabling an Interval

The refreshInterval parameter is calculated on every evaluation, even if the value of the variable is not. This is to enable you to dynamically change the value as data changes within the interface, particularly to enable and disable timers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
a!localVariables(
  local!enableTimer: false,
  local!value: a!refreshVariable(
    value: rand(),
    refreshInterval: if(local!enableTimer, 0.5, null)
  ),
  {
    a!buttonArrayLayout(buttons: {
      a!buttonWidget(
        label: if(local!enableTimer, "Disable", "Enable") & " Timer",
        saveInto: a!save(local!enableTimer, not(local!enableTimer))
      )
    }),
    a!textField(label: "Value", value: local!value, readOnly: true)
  }
)

In this example, changing the value of local!enableTimer does not cause the value of local!value to refresh, but it does enable and disable the timer.

Conditionally Enabling an Interval Based on the Current Variable Value

When configuring the value of refreshInterval, you have access to the current value of the variable using fv!value. This will allow you to enable or disable timers based on the current value of the variable.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
a!localVariables(
  local!testRunId,
  local!testRunStatus: a!refreshVariable(
    value: if(isnull(local!testRunId), null, a!testRunStatusForId(local!testRunId)),
    refreshInterval: if(or(isnull(fv!value), fv!value = "COMPLETE"), null, 0.5)
  ),
  local!testRunResults: if(
    local!testRunStatus = "COMPLETE",
    a!testRunResultForId(local!testRunId),
    null
  ),
  {
    a!buttonArrayLayout(
      buttons: {
        a!buttonWidget(
          label: "Run All Tests",
          saveInto: a!startRuleTestsAll(onSuccess: {
            a!save(local!testRunId, fv!testRunId)
          })
        )
      }
    ),
    rule!displayTestResults(local!testRunResults)
  }
)

In this example, you can dynamically enable the refreshInterval for local!testRunStatus once a new test run has been started and disable the timer again when the status is "COMPLETE".

Performance Considerations

Configuring an interface to refresh on an interval means your interface may evaluate more than it would when only relying on a user interaction. Any additional evaluations will cause additional load on your system as well as any external systems that are called when refreshing the data.

System load will vary based on the number of active auto-refreshing interfaces that are open at one time. An interface will not continue refreshing while it is inactive. An interface is inactive when the user:

  • navigates away from the interface by navigating to another interface within Appian or an external interface.
  • minimizes the browser window containing the auto-refreshing interface.
  • navigates to a different tab within the same browser window as the auto-refreshing interface, such that the tab containing the auto-refreshing interface is no longer visible.
  • closes the browser tab or window.
  • shuts down, restarts, or locks the computer with the auto-refreshing interface.

Therefore, if a user has multiple auto-refreshing tabs open at the same time, the performance impact will not scale based on the number of tabs. However, if a user has many auto-refreshing interfaces open in separate, visible windows, each interface will continue refreshing and will impact overall system load. Similarly, concurrent usage of auto-refreshing interfaces across multiple users will also affect system load.

Monitoring Performance

The Interface Performance logs provide information about the number of evaluations caused specifically by a refresh interval and the evaluation times for those evaluations. With this information you can determine:

  • how much additional load is added by the interval refresh by comparing the number of interval evaluations to the overall number of evaluations
  • if the performance of interval evaluations is comparable to user-initiated evaluations by comparing the evaluation time metrics for interval evaluations to the overall metrics

Refresh Always

Finally, a variable can also refresh on every evaluation, regardless of whether its dependencies change. The variable would be refreshed after any user interaction and after any timer causes a variable to refresh. This is configured using the refreshAlways parameter.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
a!localVariables(
  local!name: "John Smith",
  local!username: "john.smith",
  local!lastEditedTimestamp: a!refreshVariable(
    value: now(),
    refreshAlways: true
  ),
  {
    a!textField(
      label: "Name",
      value: local!name,
      saveInto: local!name
    ),
    a!textField(
      label: "Username",
      value: local!username,
      saveInto: local!username
    ),
    a!dateTimeField(
      label: "Username Last Edited",
      value: local!lastEditedTimestamp,
      readOnly: true
    )
  }
)

When using the refreshAlways configuration, there's no need to configure either the refreshOnReferencedVarChange or refreshOnVarChange parameters. This is because the variable will always evaluate regardless of whether its dependencies change or not.

Generally, you won't need to use this configuration unless your variable needs to be updated very often because the data is constantly changing outside the interface. If your variable has dependencies, you usually only want to refresh that variable when its dependencies change to improve the performance of your evaluation.

Using Local Variables in the Definition of Refreshing Variables

When you define the value of a local variable using a rule that itself contains local variables, refreshAlways may be required to get the desired behavior. By default, local variables only update their values when their dependencies change. This includes variables defined inside the definition of other variables.

For example, say you have the following interface:

1
2
3
4
5
6
7
8
9
10
a!localVariables(
  local!employee: a!refreshVariable(
    value: rule!getFormattedEmployeeInfo(ri!id),
    refreshInterval: 0.5
  ),
  {
    a!textField(label: "Name", value: local!employee.name, readOnly: true),
    a!textField(label: "Start Date", value: local!employee.startDate, readOnly: true),
  }
)

where rule!getFormattedEmployeeInfo is defined as:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
a!localVariables(
  local!origEmployeeData: a!queryEntity(
    entity: cons!EMPLOYEE_ENTITY,
    query: a!query(
      logicalexpression: a!queryLogicalExpression(
        operator: "AND",
        filters: {
          a!queryFilter(field: "id", operator: "=", value: ri!id)
        },
        ignoreFiltersWithEmptyValues: true
      ),
      pagingInfo: a!pagingInfo(startIndex: 1, batchSize: 1)
    ),
    fetchTotalCount: false
  ).data,
  local!employeeName: concat(local!origEmployeeData.firstName, " ", local!origEmployeeData.lastName),
  local!formattedStartDate: text(local!origEmployeeData.startDate, "mmm d, yyyy"),
  {
    name: local!employeeName,
    startDate: local!formattedStartDate
  }
)

Because local variables only refresh when their dependencies change by default, local!origEmployeeData does not automatically refresh when the 30 second timer on local!employee is triggered. Therefore, the data for local!employee will not change when the timer goes off, even if the underlying data has been updated in the database.

To ensure that the employee data is requeried when the timer goes off, local!origEmployeeData needs to use the refreshAlways configuration to force it to reevaluate even when its dependencies haven't changed. Don't worry, that doesn't mean the query will happen on every evaluation of the interface; because the parent variable local!employee is only evaluated on a timer, this expression will only be evaluated when the timer goes off. This configuration simply ensures that the query is always executed each time the timer goes off.

Therefore, the definition of rule!getFormattedEmployeeInfo needs to be updated to:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
a!localVariables(
!  local!origEmployeeData: a!refreshVariable(
!    value: a!queryEntity(
      entity: cons!EMPLOYEE_ENTITY,
      query: a!query(
        logicalexpression: a!queryLogicalExpression(
          operator: "AND",
          filters: {
            a!queryFilter(field: "id", operator: "=", value: ri!id)
          },
          ignoreFiltersWithEmptyValues: true
        ),
        pagingInfo: a!pagingInfo(startIndex: 1, batchSize: 1)
      ),
      fetchTotalCount: false
    ).data,
!    refreshAlways: true
!  ),
  local!employeeName: concat(local!origEmployeeData.firstName, " ", local!origEmployeeData.lastName),
  local!formattedStartDate: text(local!origEmployeeData.startDate, "mmm d, yyyy"),
  {
    name: local!employeeName,
    startDate: local!formattedStartDate
  }
)

Notice that local!employeeName and local!formattedStartDate didn't need to use refreshAlways because they only need to be recalculated if the value of local!origEmployeeData changes.

Combining Refresh Configurations

All refresh configurations can be combined to increase the frequency with which the variable is refreshed. The table below describes the behavior when different configurations are combined.

refresh Always refreshOn Referenced VarChange refreshOn VarChange refresh Interval Variable refreshed when…
any value any value the user interacts with any component in the interface
or
any timer in the interface goes off, including this one
any variables referenced in the value parameter are updated
or
any variables listed in the refreshOnVarChange parameter are updated
or
this timer goes off
any variables referenced in the value parameter are updated
or
this timer goes off
any variables listed in the refreshOnVarChange parameter are updated
or
this timer goes off
any variables referenced in the value parameter are updated
or
any variables listed in the refreshOnVarChange parameter are updated
FEEDBACK