Everything on PowerApps Offline Compatibility

Many of us can identify with this situation when you are in the middle of something and the internet goes off. The Internet can be flakey or unavailable.

Internet connection is like Catwoman charming but a duplicitous double-crossing rogue who will leave you alone at the most vulnerable state. We all have a moment when we are deceived by our internet connection, the same way when Catwoman led Batman into Bane’s trap; poor chap broke his back!

Image for post

TL;DR: In this blog, you will learn the basic concepts of creating an offline app in PowerApps. Because the internet is flaky, you’ll always need to consider that an app works when there is no network.

Introduction

PowerApps is a low code cloud-based platform. If you want to know more about PowerApps, here’s a short video.

A while ago, we were working on an app on PowerApps for the enabled users to collect field inspection details. A canvas based PowerApps was an excellent solution. However, the end user had to work in an area which might not have internet connectivity. We need to make an app that works in offline too.

I had my doubts initially. Gladly, I was wrong. A lesson learned. An app platform with Power in its name should be powerful enough to do anything.

Now, the question is how does PowerApps work offline?

In PowerApps, follow these simple steps for making the app work offline:

  • When the app loads or when a specific action is triggered, check whether there is a connectivity or not.
  • If there is connectivity, use connectors and directly take the data from the source in the cloud.
  • If there is no connectivity, save the save the data into the collection and leverage the power of `SaveData` to store locally in cache file or LoadData to fetch from locally stored data. Once there is internet connectivity, the locally stored records are stored in the data source.

To implement offline compatibility in an app you’ll need formulas below:

  • Collect, Clear, and ClearCollect functions in PowerApps
  • SaveData and LoadData
  • Connection
  • Patch

Collect, Clear and ClearCollect function
Collect is used to add records to a data source.

Syntax:

Collect( DataSource, Item, … )

Clear is used to delete records from a collection.

Syntax:

Clear( Collection )

ClearCollect is used to add fresh records to a collection by clearing all the previous records.

ClearCollect( Collection, Item, … )

Note that Clear and ClearCollect can only be applied to collections and not other data sources.

So what is a Collection?

A collection is a group of items that are similar. It is used to store the records so that it can be used in the app. For example, SuperHeroes is a collection that stores the name, planet, and girlfriend of superheroes.

Example:

Collect(
SuperHeroes,
{
Name: "Superman",
planet: "Krypton",
girlfriend: "Lous Lane"
},
{
Name: "Batman",
Planet: "Earth",
girlfriend: "Rachael Dawes, Catwoman,Wonder Woman,Talia al Ghul,Batgirl,Poison Ivy,Black Cannary,Zatana and maybe Joker too"
}
)

SaveData and LoadData

LoadData and SaveData are the only functions that allow you to store and use dynamic content locally on a device. These two functions are also always suggested when people ask how they can get their apps to work offline.

Syntax:

SaveData( Collection, Name )LoadData( Collection, Name)

Connection

The Connection signal returns the information about the network connection. When on a metered connection, you may want to limit how much data you send or receive over the network.

Syntax:

Connection.Connected //returns true if internet is connectedConnection.Metered //returns false if internet is not connected

Patch

Patch function is used to modify or create a record in a data source.

Syntax:

Patch( DataSource, BaseRecord, ChangeRecord1 [, ChangeRecord2, … ])

Scenarios:

  • Show list of records
  • Save / Update Records

Scenario 1: Show Records

To show a list of records, the app should be connected to the internet at least once. We load the records from the data source into the collection and save the records from the collection in a local cache file. If there is no internet connectivity, then we will be using the locally stored data and load it into the collection.

Example:

If(
Connection.Connected,
ClearCollect(
RecordsCollection,
'Records List'
);
SaveData(
RecordsCollection,
"RecordsInLocalStorage"
),
LoadData(
RecordsCollection,
"RecordsInLocalStorage",
true
)
)

The records collection can be used as a source of records in the application. You can use it as the data source for gallery control or any other control.

Scenario 2: Add / Update Records

Keep in mind, the following points while adding or updating the record:

  • Save all the records in the local cache when the internet is connected.
  • If internet connection is available, save/update to the Data source directly else, save or update in the local cache
  • Keep a flag in the collection to mark whether the record is a new record or the updated record
  • Once the internet is available, iterate each record of the collections
  • If the record is flagged as new, add it into the data source
  • If the record is flagged as updated, update the respective record in the data source

Example:

We have a SQL database called Pokemon, and it has two columns Name and Ability.

Adding a New Record

If(
Connection.Connected,
Patch(
'[dbo].[Pokemon]',
Defaults('[dbo].[Pokemon]'),
{
PokemonName: PokemonNameInput.Text,
PokemonAbility: PokemonAbility.Text
}
),
Collect(
PokemonOffline,
{
Name: PokemonNameInput.Text,
Ability: PokemonAbility.Text,
flag: "New"
}
);
SaveData(
PokemonOffline,
"PokemonCache"
)
)

We are adding the record of Pokemon to DataSource Pokemon if there is connectivity otherwise storing it into the local cache file keeping a flag “New”.

Updating the Record

If(
Connection.Connected,
Patch(
'[dbo].[Pokemon]',
First(
Filter(
'[dbo].[Pokemon]',
PokemonName = PokemonNameInput.Text
)
),
{PokemonAbility: PokemonAbility.Text}
),
UpdateIf(
PokemonOffline,
Name = PokemonNameInput.Text,
{
Ability: PokemonAbility.Text,
flag: "Update"
}
);
SaveData(
PokemonOffline,
"PokemonCache"
)
)

We are updating the record in the data source Pokemon if there is connectivity otherwise update in the local cache file. Here we are updating only ability searching the record from Pokemon’s name.

Syncing the record with data source

ForAll(
PokemonOffline,
If(
flag = "Update",
Patch(
'[dbo].[Pokemon]',
First(
Filter(
'[dbo].[Pokemon]',
PokemonName = Name
)
),
{PokemonAbility: Ability}
),
If(
flag = "New",
Patch(
'[dbo].[Pokemon]',
Defaults('[dbo].[Pokemon]'),
{
PokemonName: Name,
PokemonAbility: Ability
}
)
)
)
)

While synching the offline cache with the data source we are checking the flag whether it is a new record or updated record. If it is an updated record we are updating in the original data source.

The synchronization code can be triggered when a screen loads, a button is clicked, or using a timer and syncing after a certain interval of time checking the internet connectivity.

Conclusion

In this blog, I showed you how you could make PowerApps work. You can try these simple methods to build your next offline first PowerApp. If you need help, do not hesitate to leave a message in the comments section down below. Cheers!