Developing apps in PowerApps can be quite difficult in the beginning. This post is aimed at getting started with PowerApps hopefully avoiding the amount of time to get started with PowerApps. I’m by no means trying to create a full app. this is just a way to get you started.

During the first steps you likely found the way to create a new app and the templates offered look great however they aren’t what you want. Now we’ve got an empty screen and it isn’t clear what the next steps should be.

Well first of all close the above screen and think what you want to create.

A good start is to first create some mock-ups of the screens that you want to develop within you app. Today I will develop a Site Inspection app. This is one of the templates offered by PowerApps. It simply helps me to create all the screenshots while writing this post. Also it means that I don’t have to worry about displaying any customer data.

I want my dashboard to give the user options to select a site/building and then details of that site can be displayed. I’ve got something like the following dashboard in my head:

Then looking at my PowerApp I would start to identify all the other screens that I need to create.

  • Dashboard (as above)
  • New Site Inspection (this is shown when I click the + at the top of the dashboard)
  • Edit Inspection (this is shown when I click on edit
  • Delete inspection screen (this is shown when I click on delete on the dashboard)

Then for each screen I might create a mock-up like the one above.

Now Am I ready to start developing the app?

Not really. It’s important to get the data layer right. Now that we know what things look like it’s important to make the right choices.

Depending on your application you could store your data in a SQL database, the Common Data Service or even just in a spreadsheet. This is all up to you.

In this example I’m going to use a OneDrive to store my data, however you will find that often you will want to store your data in different locations. Especially, when your data models are growing you might want to make sure that you plan for the longer term as systems may become harder to manage when you make the wrong choices. In my example however I will store my data in spreadsheets in OneDrive.

Within PowerApps Studio, I’m now creating a new app and I’m back at my blank screen.

I always like to build my apps, by creating the data layer first. However for this post I will go through the planned dashboard screen from top to bottom.

Starting with the orange bar at the top. I’m adding a rectangle (this has been hidden in the Icons section in the Insert tab) to my Dashboard screen. Then I’m adding a label to get some text in the top bar and finally I add an Add icon.

The Add new icon is going to give me my first additional screen to create.  The open a new screen all you need to do is call the Navigate  function.

 Navigate(NewInspectionScreen, ScreenTransition.Fade)

The Navigate option however has an additional optional parameter Context.

Navigate(NewInspectionScreen,ScreenTransition.None,{NewRecord:true})

With this last option you can create a new record within the context of your app. You should compare the Context a bit with a list of variables that you want to keep hold off while your app is running. Do this is a good way to keep data and use it to communicate between multiple screens.

Then in my NewInspectionScreen screen I add labels and fields to make up my form.

Note that these fields are not connected to my data in any kind of way. There just text boxes that collect the data. It is possible to create forms that are connected to data, but it isn’t always the easiest to manage.

Now within a single place, we can add all the logic behind the form. By Clicking on the Don button the following code will run:

Who said that PowerApps is a no/low coding solution?

Time to have a look at the code:

If(!IsBlank(NewAddressText.Text)&&!IsBlank(NewCityText.Text)&&!IsBlank(NewZipText.Text)&&!IsBlank(NewStateText.Text)&&!IsBlank(NewTitleText.Text)&&!IsBlank(NewSubTitleText.Text)||!IsBlank(NewTitleText.Text)&&!IsBlank(NewSubTitleText.Text)&&Radio1_4.Selected.Value="Use GPS for current Location",If(CountRows(CameraPhotos)>=1,UpdateContext({AddPhoto:Patch(SitePhotos,Defaults(SitePhotos),{PhotoId:Max(SitePhotos,PhotoId)+1,Photo:Last(FirstN(CameraPhotos,1)).Photo,ID:Max(SiteInspector,ID)+1,Note:Text(Last(FirstN(CameraPhotos,1)).Note)})}));
If(CountRows(CameraPhotos)>=2,UpdateContext({AddPhoto:Patch(SitePhotos,Defaults(SitePhotos),{PhotoId:Max(SitePhotos,PhotoId)+1,Photo:Last(FirstN(CameraPhotos,2)).Photo,ID:Max(SiteInspector,ID)+1,Note:Text(Last(FirstN(CameraPhotos,2)).Note)})}));
If(CountRows(CameraPhotos)>=3,UpdateContext({AddPhoto:Patch(SitePhotos,Defaults(SitePhotos),{PhotoId:Max(SitePhotos,PhotoId)+1,Photo:Last(FirstN(CameraPhotos,3)).Photo,ID:Max(SiteInspector,ID)+1,Note:Text(Last(FirstN(CameraPhotos,3)).Note)})}));
If(CountRows(CameraPhotos)>=4,UpdateContext({AddPhoto:Patch(SitePhotos,Defaults(SitePhotos),{PhotoId:Max(SitePhotos,PhotoId)+1,Photo:Last(FirstN(CameraPhotos,4)).Photo,ID:Max(SiteInspector,ID)+1,Note:Text(Last(FirstN(CameraPhotos,4)).Note)})}));
If(CountRows(CameraPhotos)>=5,UpdateContext({AddPhoto:Patch(SitePhotos,Defaults(SitePhotos),{PhotoId:Max(SitePhotos,PhotoId)+1,Photo:Last(FirstN(CameraPhotos,5)).Photo,ID:Max(SiteInspector,ID)+1,Note:Text(Last(FirstN(CameraPhotos,5)).Note)})}));
If(CountRows(CameraPhotos)>=6,UpdateContext({AddPhoto:Patch(SitePhotos,Defaults(SitePhotos),{PhotoId:Max(SitePhotos,PhotoId)+1,Photo:Last(FirstN(CameraPhotos,6)).Photo,ID:Max(SiteInspector,ID)+1,Note:Text(Last(FirstN(CameraPhotos,6)).Note)})}));
If(CountRows(CameraPhotos)>=7,UpdateContext({AddPhoto:Patch(SitePhotos,Defaults(SitePhotos),{PhotoId:Max(SitePhotos,PhotoId)+1,Photo:Last(FirstN(CameraPhotos,7)).Photo,ID:Max(SiteInspector,ID)+1,Note:Text(Last(FirstN(CameraPhotos,7)).Note)})}));
UpdateContext({AddRecord:Patch(SiteInspector,Defaults(SiteInspector),{ID:Max(SiteInspector,ID)+1,Title:NewTitleText.Text,SubTitle:NewSubTitleText.Text,Notes:NewNotesText.Text,Description:NewDescriptionText.Text,Address:NewAddressText.Text,City:NewCityText.Text,Zip:Text(NewZipText.Text),State:NewStateText.Text,Latitude:If(Radio1_4.Selected.Value="Use GPS for current Location",Text(Location.Latitude),""),Longitude:If(Radio1_4.Selected.Value="Use GPS for current Location",Text(Location.Longitude) ,""),IsGPSCoordinates:If(Radio1_4.Selected.Value="Use GPS for current Location","True","False")})});Navigate(DashboardScreen,ScreenTransition.None));If(IsBlank(NewTitleText.Text)||IsBlank(NewSubTitleText.Text)||IsBlank(NewAddressText.Text)||IsBlank(NewCityText.Text)||IsBlank(NewStateText.Text)||IsBlank(NewZipText.Text) ,UpdateContext({Required:true}),UpdateContext({Required:false}))

 

I’m going to split the code into 2 sections.

1. Form validation

If(IsBlank(NewTitleText.Text)||IsBlank(NewSubTitleText.Text)||IsBlank(NewAddressText.Text)||IsBlank(NewCityText.Text)||IsBlank(NewStateText.Text)||IsBlank(NewZipText.Text) ,UpdateContext({Required:true}),UpdateContext({Required:false}))

The above if displays a warning that not all required fields have been filled in.

By updating a Required variable in my context. All I need to do to make the warning visible is use that same variable in the visibility of the warning box.

Another part of the validation is the validation before saving the data.

If(!IsBlank(NewAddressText.Text)&&!IsBlank(NewCityText.Text)&&!IsBlank(NewZipText.Text)&&!IsBlank(NewStateText.Text)&&!IsBlank(NewTitleText.Text)&&!IsBlank(NewSubTitleText.Text)||!IsBlank(NewTitleText.Text)&&!IsBlank(NewSubTitleText.Text)&&Radio1_4.Selected.Value="Use GPS for current Location",If(CountRows(CameraPhotos)>=1,UpdateContext({AddPhoto:Patch(SitePhotos,Defaults(SitePhotos),{PhotoId:Max(SitePhotos,PhotoId)+1,Photo:Last(FirstN(CameraPhotos,1)).Photo,ID:Max(SiteInspector,ID)+1,Note:Text(Last(FirstN(CameraPhotos,1)).Note)})}));

So by checking all of my fields’s values the form is validated.

2. Update the Context with the new record

UpdateContext({AddRecord:Patch(SiteInspector,Defaults(SiteInspector),{ID:Max(SiteInspector,ID)+1,Title:NewTitleText.Text,SubTitle:NewSubTitleText.Text,Notes:NewNotesText.Text,Description:NewDescriptionText.Text,Address:NewAddressText.Text,City:NewCityText.Text,Zip:Text(NewZipText.Text),State:NewStateText.Text,Latitude:If(Radio1_4.Selected.Value="Use GPS for current Location",Text(Location.Latitude),""),Longitude:If(Radio1_4.Selected.Value="Use GPS for current Location",Text(Location.Longitude) ,""),IsGPSCoordinates:If(Radio1_4.Selected.Value="Use GPS for current Location","True","False")})});

 

Ok, so now we have a record in our context that can be used. Before continuing these adventures in PowerApps development. I first want to have a look at some best practises. By looking further at the above code snippets. What does Radio1_4.Selected.Value mean? Well this isn’t very clear coding. The examples/templates offered by PowerApps aren’t great! When you create any screens or controls it is a great habit to rename the the controls straight away. Radio1_4 might not be too much of a problem when you only have one radio control on your form but when you have multiple this is a real pain. Therefore when I develop my apps I rename every RadioX_X to something sensible. So in this case I would rename it to RadioLocation This way it is still clear that I’ve got a radio button and at the same time my code becomes easier to understand.

Now that we’ve got all the basics in place it is just a matter of adding more screens to the solution and adding more shapes to my screens. If you need any further help or if you would like me to extend this post feel free to leave a comment below. Even if you would like me to help you develop your applications just contact me and I’m happy to help.

 

Advertisements