{"id":123,"date":"2018-01-30T07:50:41","date_gmt":"2018-01-30T15:50:41","guid":{"rendered":"https:\/\/www.microsoft.com\/en-us\/power-platform\/blog\/power-apps\/implementing-offline-capability-in-your-app\/"},"modified":"2025-06-11T08:10:02","modified_gmt":"2025-06-11T15:10:02","slug":"implementing-offline-capability-in-your-app","status":"publish","type":"post","link":"https:\/\/www.microsoft.com\/en-us\/power-platform\/blog\/power-apps\/implementing-offline-capability-in-your-app\/","title":{"rendered":"Implementing Offline Capability In Your App"},"content":{"rendered":"
Do you want to build offline capabilities in your PowerApps app because your app users need to access some data or save some data even when they don’t have the internet connection? This blog provides an example of building these offline capabilities in your PowerApps app. This article assumes that you already know the basic concepts of PowerApps like screens, controls, events, attributes, navigation etc. We’ll will use all these concepts in this tutorial.
\n\u00a0<\/p>\n
The offline feature area is still under development and is not optimized for every offline scenario today. The functions to SaveData() to a local device and LoadData() from that device work best in their current implementation over relatively small quantities of data (e.g., dozens of text records in a table) that generally do not exceed 2MB. This is useful for some basic \u201coffline\u201d scenarios as well as to increase the startup performance of canvas apps by caching data locally. However, using this feature to save large amounts of data (e.g., saving thousands of rows in a table, or caching large images or videos) may cause errors or unexpected behavior with the current implementation and should be avoided. Also, the functions do not automatically resolve merge conflicts when a device returns to connectivity from offline \u2013 configuration on what data is saved and how to handle reconnection is up to the maker when writing expressions. We are working to expand the capabilities of offline apps to increase stability and size limits, and in the future to automatically handle decisions about what to save and how to handle conflicts. Stay tuned here and on the PowerApps blog for updates when they become available.\u00a0<\/em><\/p>\n \u00a0<\/p>\n For this tutorial, let\u2019s assume we have to build a simple Issue Reporting App with the following requirements:<\/p>\n \u00a0<\/p>\n \u00a0<\/p>\n \u00a0<\/p>\n High Level Approach for accomplishing this is:<\/p>\n \u00a0<\/p>\n For this app, I created a very simple custom entity \u201cIssue List\u201d in CDS (Common Data Service) to capture issues with \u201cTitle\u201d and \u201cDescription\u201d as 2 custom fields. \u00a0<\/p>\n \u00a0<\/p>\n First screen in this sample app is a cover page kind of screen. On the click of \u201cLet\u2019s Go\u201d button, we\u2019ll check the internet connection via an object exposed by PowerApps called \u201cConnection\u201d. If internet connection is available (i.e. Connection.Connected is true), populate the local collection \u201cIssueCollection\u201d directly from the entity \u201cIssue List\u201d in the CDS database. Also, save it to the local storage (local cache) as \u201cissuesInLocalStorage\u201d so that we can use it as local cache when the internet connection is not available. If internet connection is not available, populate \u201cIssueCollection\u201d from this local cache. Finally, put the formula to navigate to the next screen where we\u2019ll be using the \u201cIssueCollection\u201d collection as the data source (Items property) for the gallery to show all the issues.<\/p>\n \u00a0<\/p>\n Following is the formula to be written on OnSelect event of the\u00a0 button \u201cLet\u2019s Go\u201d:<\/p>\n If(Connection.Connected,<\/p>\n ClearCollect(IssueCollection, ‘Issue List’);<\/p>\n SaveData(IssueCollection,”issuesInLocalStorage”), );<\/p>\n Navigate(IssueListScreen,ScreenTransition.Cover)<\/p>\n \u00a0<\/p>\n Note- I chose the option to do all this work in the OnSelect event of a button. You are free to use a different approach like doing all this work in the OnStart event of the app or OnVisible event of the screen.<\/p>\n \u00a0<\/p>\n \u00a0<\/p>\n Now, on the next screen (\u201cIssueListScreen\u201d), insert a gallery and set the Items property of that gallery to \u201cIssueCollection\u201d. Show the Title and Description fields in the gallery. That\u2019s it for the first requirement. Your app is now ready to show data directly from the data source or local cache depending on the internet connection availability.<\/p>\n \u00a0<\/p>\n Test it by first opening the app and seeing the gallery data with the internet connection on your phone. Close the app and now turn the phone in the airplane mode. Open this app again and hit \u201cLet\u2019s Go\u201d. You should see the issue list coming from Local Cache.<\/p>\n \nImportant Note- As of now, you can\u2019t test the LoadData and SaveData in browser. You must use your mobile device to test that part. In the web editor, you might see the error for LoadData and SaveData. Please ignore that.<\/p>\n \u00a0<\/p>\n For adding new issues, add a new screen \u201cNewIssueScreen\u201d and insert an EditForm control in that screen. Navigate to this screen on the press of plus sign from the “IssueListScreen\u201d. Our high level approach for save new data (new issue for our app) will be as follows: Following is the formula to be used on the \u201cOnSelect\u201d event of a save button:<\/p>\n \nIf(Connection.Connected,SubmitForm(EditForm1); Refresh(‘Issue List’); ClearCollect(IssueCollection,’Issue List’); Navigate(IssueListScreen,ScreenTransition.Cover)<\/p>\n<\/blockquote>\n \u00a0<\/p>\n \u00a0<\/p>\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 If(CountRows(IssuesToBeAdded) >0,CountRows(IssuesToBeAdded) & ” offline issues to be added”, “0 offline issues. All caught up.\u201d) \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Below is the formula for OnTimerEnd event of the timer:<\/p>\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 If(Connection.Connected && CountRows(IssuesToBeAdded) >0,<\/p>\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Collect(‘Issue List’,IssuesToBeAdded);<\/p>\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Clear(IssuesToBeAdded);<\/p>\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 SaveData(IssuesToBeAdded,”newIssuesInLocalStorage”);<\/p>\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Refresh(‘Issue List’);<\/p>\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ClearCollect(IssueCollection, ‘Issue List’);<\/p>\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 SaveData(IssueCollection,”issuesInLocalStorage”))<\/p>\n \u00a0<\/p>\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 With this, we are all set with saving the offline issues to database as soon as the connection is available and also getting a label to tell us how many issues are offline issues to be saved.<\/p>\n If(Connection.Connected, ClearCollect(IssueCollection, ‘Issue List’);SaveData(IssueCollection,”issuesInLocalStorage”), LoadData(IssuesToBeAdded,”newIssuesInLocalStorage”, true); <\/strong>Navigate(IssueListScreen,ScreenTransition.Cover)<\/p>\n \u00a0<\/p>\n Side note- Caching data is a good strategy for your app performance as well. You can learn more about performance tips for your apps in this blog<\/a>.<\/p>\n \u00a0<\/p>\nOffline Requirements Of An Example Issue Reporting App<\/h2>\n
\n
<\/a><\/p>\n\u00a0<\/h3>\n
Note:<\/h3>\n
\n
\n\t\u00a0<\/li>\nPart 1:\u00a0 Build Offline Cache of the Issue List: Show Online or Offline List Depending On the Internet Connection Availability<\/h2>\n
\n
\nNote- I used CDS as the data source for my app. You can also use any other data source like SQL, SharePoint Online etc for creating similar table. Offline implementation concepts will be same.<\/p>\n
<\/a><\/p>\n
\nLoadData(IssueCollection,”issuesInLocalStorage”, true)<\/p>\n
<\/a><\/p>\n
<\/a><\/p>\n\u00a0<\/h2>\n
Part 2: Capture new issues even when internet connection is not available and save to the database when the internet connection becomes available<\/h2>\n
\n\u00a0<\/p>\n\n
\n
\n
\n\t\t\u00a0<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n
\nSaveData(IssueCollection,”issuesInLocalStorage”)
\n,
\nCollect(IssuesToBeAdded,{Title:TitleDatacard.Text,Description:DescriptionDatacard.Text} ); SaveData(IssuesToBeAdded, “newIssuesInLocalStorage”));<\/p>\n\n
<\/a><\/p>\n<\/blockquote>\n\n
\n\t\u00a0<\/li>\n\n
\n
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/p>\n<\/blockquote>\n\n
\n
\n
\n
<\/a>
\n\u00a0<\/p>\n\n
\nLoadData(IssueCollection,”issuesInLocalStorage”, true));<\/p>\n