The capabilities described on this page are included in Appian's advanced and premium capability tiers. Usage limits may apply. |
IntroductionCopy link to clipboard
When you enable an interface for offline use, you are changing the way the interface communicates with the server when accessed on Appian Mobile.
On desktop and mobile browsers, offline interfaces evaluate the same as any other interface. However, when accessed on Appian Mobile, offline interfaces do not communicate with the server, except during an offline data sync. This is true whether the user is online or offline.
Basically, offline interfaces are different from standard interfaces in the following ways:
- In Appian Mobile, offline interfaces only communicate with the server during an offline data sync.
- During this sync, anything stored in local variables at the top of the interface is cached to the user's device so that they can access it while offline.
Because of this, you need to design offline interfaces with certain principles and best practices in mind. This page outlines what to consider when designing offline interfaces.
Caution: Always fully test offline interfaces in the Appian Mobile app, making sure to complete all fields, to prevent issues that could cause users to lose their work.
Working with dataCopy link to clipboard
Since offline interfaces only connect to the server during an offline data sync, you'll need to consider how you query data in an offline interface. The following sections outline some query best practices to use in your offline interfaces.
Query all data in a local variable at the top of the interfaceCopy link to clipboard
GuidelineCopy link to clipboard
Query all data in local variables or rule inputs at the top of the interface so that they evaluate on the first load of the interface.
ImportanceCopy link to clipboard
During an offline data sync, all offline interfaces run through their initial evaluation. Only local variables defined at the top of the interface, before any components, are included in this initial evaluation. The data queried within these local variables is the only data available in an offline interface.
Attempting to query data elsewhere in the interface will result in an error on Appian Mobile, as offline interfaces cannot communicate with the server outside of an offline data sync.
Example: Querying data in a local variable at the top of an interfaceCopy link to clipboard
In this example, we query data in a local variable at the top of the interface so that we can use this data throughout the interface.
The rule!getAllCustomers()
rule could be any number of methods used to get data such as a!queryRecordType() or an integration.
Compatible | Not Compatible |
---|---|
|
|
Query data for child interfaces or rules at the top of the parent interfaceCopy link to clipboard
GuidelineCopy link to clipboard
When using child interfaces or rules, query the data in a local variable at the top of the parent interface and pass it to the child using a rule input.
ImportanceCopy link to clipboard
During an offline data sync, only the data in the parent interface is downloaded to the user's device. If you try to query the data in the child interface or rule, it will cause an error on Appian Mobile.
ExampleCopy link to clipboard
In the following example, the data is queried in a local variable at the top of the parent interface. The variable is then used for the data parameter value for the child interface.
In the child interface, we use a rule input for the data parameter. This ensures that no querying happens in the child interface.
Compatible | Not Compatible |
---|---|
Parent interface
Child interface: `rule!childGridInterface()`
|
Parent interface
Child interface: rule!childGridInterface()
|
Only query the data you needCopy link to clipboard
GuidelineCopy link to clipboard
Limit your queries to retrieve only the necessary data for your interface. You can do this by:
- Using filters to return specific data.
- Including only the required fields in your query.
- Using paging to limit the number of results.
ImportanceCopy link to clipboard
Offline interfaces must download data to a user's device, and the speed of this download depends on the device hardware and the amount of data being downloaded. Downloading too much data can slow down performance, particularly on less powerful mobile devices.
Example: Only query the data you needCopy link to clipboard
The following example only returns the id, name, email, and billing address for a customer, rather than returning all fields. It also uses paging and filtering to further filter the information.
Compatible | Not Compatible |
---|---|
|
|
Working with charts and read-only gridsCopy link to clipboard
For the data parameter, use a local variable that calls a!queryRecordType()Copy link to clipboard
GuidelineCopy link to clipboard
When displaying a chart or read-only grid in an offline interface, don't reference a record type directly in the data parameter. Instead, query the record type in a local variable and reference the local variable in the grid.
ImportanceCopy link to clipboard
During an offline data sync, only data queried in local variables at the top of the interface is downloaded to the user's device. If a chart or grid references a record type directly in its data parameter, the query is moved to the component, preventing the data from being downloaded for offline use and causing the interface to error on Appian Mobile.
ExampleCopy link to clipboard
In the following example, we query the Inspection record type in a local variable, instead of referencing the record type in the data parameter of the grid.
Compatible | Not Compatible |
---|---|
|
|
Only use parameters that work in an offline interfaceCopy link to clipboard
GuidelineCopy link to clipboard
For read-only grids and charts in offline interfaces, do not use the parameters listed in the following table:
Component | Parameters to avoid |
---|---|
Read-only grid |
|
Chart |
|
ImportanceCopy link to clipboard
Grid header, record action, and load data async parameters don't work in offline grids and charts because they require you to reference a record type in the data parameter.
Refresh parameters don't work in offline read-only grids or charts because they trigger a server call. Since offline interfaces can only communicate with the server during an offline data sync, this would cause the interface to error on Appian Mobile.
Working with partially compatible functionsCopy link to clipboard
Get the value for the function in a local variable at the top of the interfaceCopy link to clipboard
GuidelineCopy link to clipboard
To use functions that are partially compatible with offline mobile, load them in a local variable at the top of the interface.
ImportanceCopy link to clipboard
Functions that are partially compatible with offline mobile require a server connection in order to evaluate. By loading these functions and components at the top of the page, they can run during the initial evaluation during an offline data sync. But they cannot run during a reevaluation while the user is offline.
If partially compatible functions are used outside of these variables, they will try to evaluate when the interface can't communicate with the server and will cause an error in Appian Mobile.
ExampleCopy link to clipboard
For example, even though loggedInUser() isn't supported for offline reevaluations, you can still use this function by saving the resulting value into a local variable at the top of the interface.
When the user performs an offline data sync, the interface will automatically load all offline interfaces in the background and get the value for loggedInUser()
. When the user goes offline, it will use the value that was updated when they last refreshed.
If you tried to use loggedInUser()
in the saveInto parameter, it would return an error on Appian Mobile since it cannot connect to the server to get the value.
Compatible | Not Compatible |
---|---|
|
|
Set the refreshOnReferencedVarChange parameter to falseCopy link to clipboard
GuidelineCopy link to clipboard
When you use a local variable to store the value of partially compatible functions in offline interfaces, use a!refreshVariable() to set the value of refreshOnReferencedVarChange to false.
Tip: The other refresh parameters are not compatible with offline mobile as well. We're not specifying them here since they are not enabled by default. Since local variables automatically refresh when a referenced variable changes, you must manually disable this behavior.
ImportanceCopy link to clipboard
By default, all local variables automatically refresh whenever a variable they reference is updated. If that refresh happens while the interface can't communicate with the server, it would cause the interface to error on Appian Mobile.
ExampleCopy link to clipboard
For example, imagine you have a list of users that you want to query. However, the username is in the format "firstname.lastname" and you would like to display it as "Firstname Lastname."
If you are designing the interface for offline use, you would want to store the list of users in a local variable at the top of the interface.
You can then store the prettified version of the names into another local variable. If you use a!refreshVariable()
and set the value of refreshOnReferencedVarChange to false
, you can ensure this variable is only evaluated when the interface is first loaded. If refreshOnReferencedVarChange is not set to false
and local!users
is updated in a saveInto somewhere else in the interface, local!usersForDisplay
would automatically update and attempt to use the user()
function offline, which would result in an error.
Compatible | Not Compatible |
---|---|
|
|
Working with partially compatible functions in child interfaces and expression rulesCopy link to clipboard
It's common to nest child interfaces and expression rules within a parent interface. However, if these children use a partially compatible function, you need to get the value of the function in the parent interface.
For child expression rules, you can simply put the expression rule in a local variable at the top of the parent interface. However, this won't work for child interfaces since you should avoid loading interfaces in local variables. Instead, you will need to pass the value of the partially compatible function from the parent to the child interface.
For child expression rules, load the expression rule at the top of the parent interfaceCopy link to clipboard
GuidelineCopy link to clipboard
In an offline interface, when you reference an expression rule that uses a partially compatible function, put the expression rule in a local variable at the top of the parent interface.
ImportanceCopy link to clipboard
Partially compatible functions can only be evaluated during an offline data sync, which evaluates only the parent interface. In order to use a partially compatible function in a child expression rule, you need to get the value for the expression rule during this data sync. If you try to use the expression rule elsewhere in the parent interface, the interface will error in Appian Mobile.
ExampleCopy link to clipboard
In the following example, we are using a partially compatible function, loggedInUser()
, in an expression rule. We are calling the expression rule in a local variable at the top of the parent interface. This ensures that the value for the partially compatible function is saved during an offline data sync.
Compatible | Not Compatible |
---|---|
Parent interface
Child rule: `rule!childRule()`
|
Parent interface
Child rule: rule!childRule()
|
For child interfaces, pass the value of partially compatible functions from the parent to the child interfaceCopy link to clipboard
GuidelineCopy link to clipboard
In an offline interface, when you use child interface that contains partially compatible function, put the partially compatible function in a local variable at the top of the parent parent interface. Then pass the value of the function to the child interface using a rule input.
ImportanceCopy link to clipboard
Partially compatible functions can only be evaluated during an offline data sync, which evaluates only the parent interface. In order to use a partially compatible function in a child interface, you need to get the value for the function during this data sync. If you try to use a partially compatible function directly in the child interface, it will cause an error in Appian Mobile.
ExampleCopy link to clipboard
In the following example, we get the value of the partially compatible function in a local variable at the top of the parent interface. We then use that variable for the text parameter value in the child interface.
In the child interface, we use a rule input for the text parameter. This ensures that the value for the partially compatible function can be saved during an offline data sync.
Compatible | Not Compatible |
---|---|
Parent interface
Child interface: `rule!childInterface()`
|
Parent interface
Child interface: rule!childInterface()
|
Avoiding incompatible capabilitiesCopy link to clipboard
Don't use incompatible functions and componentsCopy link to clipboard
GuidelineCopy link to clipboard
Do not use incompatible functions or components in an offline interface. For more information about determining compatibility, see Determining function and component compatibility.
ImportanceCopy link to clipboard
While many functions and components work offline, there are some that won't due to their nature. Certain functions and interface components only work if they are connected to the server. Therefore, they cannot be used for offline interfaces.
ExampleCopy link to clipboard
In the following example, we use the dropdown component instead of the user picker component since the user picker isn't compatible with offline mobile.
Compatible | Not Compatible |
---|---|
|
|
Don't use plug-insCopy link to clipboard
GuidelineCopy link to clipboard
Do not use plug-ins in an offline interface. This includes function, smart service, and component plug-ins.
ImportanceCopy link to clipboard
Plug-ins are not compatible with offline interfaces and will cause the interface to error when accessed on Appian Mobile.
Working with documentsCopy link to clipboard
You can download documents in offline interfaces. Whether you want to include an image for a stylized billboard or bring in reference documents specific to user tasks, you can include any document in offline interfaces that your users can download.
To download documents offline, simply save your document as a document data type or as a document or folder data type. Then, use a document download link to call the document using one of the following methods:
- Using a constant.
- Casting document IDs using a query.
- Casting document IDs using a local variable.
For all three methods, you'll need to do all your calling, querying, and casting in local variables at the top of the interface.
Downloading documents using constants or functionsCopy link to clipboard
In some of your offline interfaces, you may want to include a document that won't regularly change. These could be an image to show in a billboard, a document with additional details and instructions, or any document that won't change from user to user.
There are two methods that you can use to download these kinds of documents:
Download documents using a constantCopy link to clipboard
When building offline interfaces, using a constant is the easiest and recommended method for calling in a document that won't regularly change. Simply create a constant that calls your document and use it in a local variable at the top of your interface.
Example: Downloading documents offline using a constantCopy link to clipboard
Compatible | Not Compatible |
---|---|
|
|
Download documents using the todocument functionCopy link to clipboard
If the document that you want to include in your offline interface is saved as a document ID of type integer, you need to cast it to a document type.
To cast the integer to a document within the interface, use the todocument()
function within a local variable at the top of the interface. If you use it farther down in the expression, the interface will attempt to return the document while offline and will not be able to retrieve it.
Example: Casting document id to document type using todocument()Copy link to clipboard
Compatible | Not Compatible |
---|---|
|
|
Downloading documents offline using a queryCopy link to clipboard
In some of your offline interfaces, you may need to include documents that will change based on the user's needs. These could be reference images specific to an inspection or previously submitted photos for equipment comparison.
These documents are typically stored in a database and you can access them using a!queryRecordType()
.
Make sure that the document you want to include is stored as a document data type or as a document or folder data type. If your document is saved as any other data type, you must cast it to a document data type or a document or folder data type so that you can download it. You can do this within local variables at the top of your interface.
Working with CDTsCopy link to clipboard
More often than not, you'll want to use record types to work with data in your offline interfaces and expressions. However, if you are already using CDTs in your application, consider the following best practices for working with CDTs.
To write data using CDTs, create CDTs that include only the fields you are writingCopy link to clipboard
GuidelineCopy link to clipboard
If you using CDTs to write data, create a CDT that only includes the fields that you are updating. Use this CDT to write only the updated fields to the data store.
ImportanceCopy link to clipboard
When you write a CDT to a database, all of the fields in the database get updated, whether you entered a value or not. This means that if you're trying to only update the first name in a database using a Customer CDT, if you don't set the values for all of the other fields, you could overwrite all of the other fields with null.
Note: Keep in mind that when we need to deal with conflicting database entries in offline mobile, we choose the most recent database entry as the source of truth.
ExampleCopy link to clipboard
For example, imagine you have an offline interface that queries for the following fields at the top of the interface.
- Customer id
- Customer name
- Customer address
In the interface, you allow the user to update the customer's address, but no other fields. To write this information to the data store, you need to create a CDT with only the id and the address fields. If you were to write to the data store using the original CDT, when you write the new address, you would update all of the other fields to null
.
Avoiding pending offline forms submission failuresCopy link to clipboard
In some cases, offline forms for site actions and tasks that are in the Pending Forms list may fail to submit after users regain connectivity. The following sections outline guidelines to follow to avoid these issues.
Be careful when modifying CDTsCopy link to clipboard
If your offline interface uses a type constructor to reference or save data to a CDT, be cautious when making changes to the CDT structure.
Adding new fields is backward-compatible and will not cause issues with pending forms.
However, the following changes can break compatibility with older versions of the CDT. This may prevent pending forms from being submitted, requiring users to fill out the form again.
CDT changes to avoid:
- Deleting fields.
- Changing a field's name.
- Changing a fields data type.
To avoid submission failures:
- Only add fields to CDTs.
- If you need to delete or rename a field, or change a field's data type, create a new CDT instead of modifying an existing one.
- Avoid using type constructors in offline interfaces. Instead, use a map and save it to a rule input of the CDT type.
Don't make changes to process calendars when users are working offlineCopy link to clipboard
If you're using a custom process calendar, avoid making changes to the calendar while users are filling out offline forms. It could cause pending form submission failures. Instead, schedule these changes during off-hours.
Make sure users have the correct folder permissions to upload filesCopy link to clipboard
If offline users attempt to upload a file to a folder that they don't have permission to access, the form will fail to submit. The offline form cannot check that the user has permission to access the folder until the user is back online, so the user won't see an error when they complete the form.
To prevent this, make sure that all users have the necessary permission to upload documents to the target folder.
Providing a better user experienceCopy link to clipboard
To allow users to submit forms automatically when their session has timed out, enable remember meCopy link to clipboard
If a user is offline for longer than the idle session timeout period and remember me is not enabled, pending forms will not be submitted until after the user manually signs in again. To allow pending forms to be submitted automatically when the user is back online, enable remember me.
Remember me is configured in the Admin Console. See Appian authentication or SAML authentication depending on the authentication that your environment uses.
Determining function and component compatibilityCopy link to clipboard
Because offline-enabled interfaces don't communicate with the server the same way that other interfaces do, certain functions and components that rely on a connection to the server work differently in offline interface.
Functions and components can be either compatible, partially compatible, or incompatible with offline mobile.
- Compatible: Works anywhere in an offline mobile interface.
- Partially compatible: Works with offline mobile if it is loaded at the top of the interface in a local variable.
- Incompatible: Doesn't work in offline mobile because it requires a connection to the server.
There are two main ways to determine whether a function or component is compatible with offline mobile: the Appian All Functions table in the docs and Appian design guidance in an interface or expression rule.
Using the Appian Functions table to determine compatibilityCopy link to clipboard
To find out if a function is compatible with offline mobile using the filters on the Appian All Functions table:
- Go to the All Functions page.
- Change the Any Compatibility dropdown list to Incompatible, Partially Compatible, or Incompatible.
- For the next dropdown list, choose Offline Mobile.
- To view the offline compatibility in the table, toggle on the Compatibility column.
Using design guidance to determine compatibilityCopy link to clipboard
A design guidance recommendation will display if you try to use an incompatible or partially compatible function in:
- Offline-enabled interfaces.
- Interfaces or expression rules that are referenced in an offline-enabled interface.
If you see this design guidance:
- For incompatible functions or components, refactor your expression to remove them.
- For partially compatible functions, use them in a local variable at the top of the parent interface.