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:
[code lang=text]
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}))
[/code]
I’m going to split the code into 2 sections.
1. Form validation
[code lang=text]
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}))
[/code]
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.
[code lang=text]
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)})}));
[/code]
So by checking all of my fields’s values the form is validated.
2. Update the Context with the new record
[code lang=text]
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”)})});
[/code]
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.
Hi Pieter, very nice start thankyou. Looking forward to seeing part 2, and an introduction to AppContext. I thought I would try and throw something together in powerapps few weeks ago and found it a very confusing paradigm to get into. All I wanted to do was click a button and update a SharePoint list column with the current DateTime, but couldn’t immediately jump into it and get it done. I’m sure it’s easy for someone familiar with the environment, which I plan to be. Your writing is appreciated.
Hi Brenton,
Thanks, for your comment. I will have a look at writing some posts about contexts in PowerApps.
To update a SharePoint list with some values you should be able to go to the SharePoint list. Create the App from the list and then PowerApps will generate the form that you need for you. Then the current value of the date field that you are looking to update could have a value of the current date in it.
[…] my introduction post about How to develop your apps in PowerApps. Today a second post about the developing PowerApps basics as it seems to be difficult to get […]
Very informative, thank you! I’m having a great deal of difficulty getting my first app to be functional. I’ve programmed with MS Access for about 20 years, so I don’t understand how this can be so difficult for me. I’ll take any help you would be willing to provide.
Hi Scott, I am always happy to help. Do you have any specific problems?
Feel free to contact me directly via the contact page. Where are you located? I can try and find a local expert for you.
[…] PowerApps – How to develop your apps in PowerApps? by Pieter Veenstra […]
Hi Pieter Is there a way of having fields at the bottom of a screen – say like a footer where you may have the fields Created, Created By, Modified and Modified By Thanks Nigel
Hi Nigel,
As these fields are just fields and within PowerApps you can set text label values to anythings you like I can’t see a reason why you wouldn’t be able to do that.
Thanks Pieter
Where is Rectangle shape? I don’t see it in ‘Icons’ menu.. There are some icons like ‘Add’, ‘Cancel’ and so on.. Is this tutorial actual?
the rectangle is there. it is quite far down in the icons.
This is now a template is MS Powerapps, how do we connect this to new data without having to update a trove of code?
Hi Brittany,
there will always be some configuration changes to make. This is why in general I would use the templates to feed ideas rather then a turn key solution.