Learn how to create a fully functional app in this step by step guide
In this exercise, our goal is to develop a Power App, allowing employees within a company to reserve parking spaces for specific dates.
The implementation will consider the following rules
- There are four available parking spaces.
- Each individual can only reserve one parking space.
- The app should display a list of individuals who have booked a parking space.
- Users should have the capability to delete (only) their own bookings.
For the purpose of this exercise, we will mainly focus on the technical solution.
SharePoint
Let’s initiate the process by setting up a new SharePoint list to serve as our database.
We only need to create 2 columns
Create a new list and name it Parking
Column names
- BookedBy (Type: Person): This column will record the individual responsible for the booking.
- BookedDate (Type: Date): This column will store the date for which the parking space is reserved.
It’s important to note that the internal name of the SharePoint column will be based on the initial name you provide.
I advice to avoid spaces or non-English letters in the column internal names.
Although SharePoint allows renaming columns later, the internal name remains fixed once set.
You can already now create a few items in the list.
Power Apps
Now that our database is prepared let’s create a new canvas app.
Go to make.powerapps.com and select Create and Blank app
When prompted about what type of app, select Blank app
Name the app Book parking space and select Phone under format and click Create
Add a data source
To include your previously created Parking SharePoint list as a data source, navigate to the Data section in the left-hand panel and select Add data
Choose the site were you created your list and select the Parking list and then click on Connect
The SharePoint list has been added as a data source
Yeeeehaa!
We’ve successfully set up an app with a connection to our data source.
Now, we can dive into saving and displaying data from this source!
As mentioned earlier we won’t spend much time on the design aspect.
While it’s generally a good practice to rename your elements during app creation, let’s skip that for now—ain’t nobody got time for that while learning.
Let’s proceed by adding the following elements to the app.
- Icon
- Cars
- Label
- Book parking space
- Label
- Select date
- Date Picker
- Button
- Book parking
- Label
- Spots available
- Vertical gallery
- (don’t select a source yet)
Press F5 and see your app in action. At this point, the only functionality we have is the ability to modify the date.
Clicking the button Book parking doesn’t trigger any specific actions, and our gallery has no data.
Press F5 again to exit the preview of the app.
Vertical gallery
If you have not already added items in your SharePoint list, go back and add a couple of items.
Once done, navigate to Data in PowerApps and, under the three dots, choose Refresh
Now, let’s add some data to our gallery.
Select the Items property for the Vertical Gallery and write Parking
Power Apps is trying to help us, and automatically inserts some details from our SharePoint list.
There are just a few issues.
- It only displays the name.
- There’s no image.
- It doesn’t consider the selected date.
In many cases you can use the Blank vertical gallery and start by building your own design.
Time to dive into some code
Our goal is to customize our vertical gallery to display only items corresponding to the selected date in our DatePicker.
In simple terms, we want to filter our Parking SharePoint list based on the BookedDate column, which we have selected in our DatePicker
Filter(Parking, BookedDate = DatePicker1.SelectedDate)
Run you app (F5) and see how the data is changing when you are changing the date in your DatePicker
Next, let’s make some changes to the gallery layout.
First, add a headline named Booked by and insert a Trashcan icon.
For the user picture, we want to utilize the Office 365 user photo.
To access this data source, go to Data and include Office 365 Users as a source.
Select the Image and use the following code in the Image property:
Office365Users.UserPhoto(ThisItem.BookedBy.Email)
This way, you can display the photo of the user who booked the parking space.
However, we’ve encountered a problem.
When selecting a date with no bookings we are getting a big red nasty error that there is no user photo available.
Also, if the user doesn’t have a photo, a white square is displayed
Dealing with user fields in PowerApps/SharePoint can be challenging
Head to Google, find a suitable No User photo, and upload it under media (I named my photo “NoUser”).
Now, add the following code to the Image property
If(
IfError(
Office365Users.UserPhotoMetadata(ThisItem.BookedBy.Email).HasPhoto = true,""
),
IfError(
Office365Users.UserPhoto(ThisItem.BookedBy.Email),""
),
NoUser
)
This code includes an if statement. If the user has a photo, it will be displayed, otherwise, the NoUser photo will be shown.
Additionally, we added an IfError function to “hide” the error message. If the user has no photo, the function returns nothing ("").
The part that hides the error message is
IfError(Office365Users.UserPhoto(ThisItem.BookedBy.Email),""),
We will revisit the gallery later to work with the Trashcan enabling users to remove their own bookings.
Book parking button
Now, let’s focus on the Book parking button.
We are going to work with the Patch function within the OnSelect property.
The Patch function can be complex, but fortunately Microsoft has provided a helpful you can find here
In our case, the function is a bit complex since we’re dealing with patching a user field.
In simpler terms, we want to send the selected date from our DatePicker to the Parking SharePoint list.
We want to send the details of the user who is currently logged in
Add this code to the OnSelect property of the button
Patch(
Parking,
Defaults(Parking),
{
BookedDate: DatePicker1.SelectedDate,
BookedBy: {
Claims: User().Email,
DisplayName: "",
Email: "",
Picture: "",
Department: "",
JobTitle: ""
}
}
);
A few things to note
Refering to the Microsoft article, we are using Defaults because we’re creating a new record, not modifying an existing one.
The selected date from the DatePicker is patched into the BookedDate field BookedDate: DatePicker1.SelectedDate)
For the BookedBy column, we patch the user’s email using User().Email
Power Apps / SharePoint expects additional information like DisplayName, etc., but we don’t control that information.
Therefore we add some blank values and rely on SharePoint/Microsoft 365 to manage the rest.
Try to remove ex. Email: "" from the code and see the error you get in your code.
Run your app and click the Book parking button to test the functionality.
So far so good, but it looks like we still have a few things we need to take care of
- The user can’t remove their own bookings
- The user can book more than 1 parking space
- The user can remove other peoples bookings
- The users can book all the parking spaces they want (we only have 4 available)
Let’s begin with the trashcan. It’s easier when testing, that we can add/remove a record within the app.
When I first started with PowerApps it took me forever to figure out how to remove an item from a gallery, but it’s quite straightforward, I don’t think it requires any additional explanation
Add this code to the trashcan icon for the OnSelect option
Remove(Parking, Gallery1.Selected)
To ensure that the users can only delete their own records, we will modify the DisplayMode option of the trashcan.
In natural language we want to make the trashcan selectable (edit) if the BookedBy.Email is the same as the current user “User().Email”, otherwise it should be disabled (or hidden, if preferred)
Add this code to the DisplayMode property of the button
If(
ThisItem.BookedBy.Email = User().Email,
DisplayMode.Edit,
DisplayMode.Disabled
)
X parking spaces available
Now we must track number of booked parking spaces, since we only have 4 available.
We want to create a variable Set(variableName) that holds the number of booked parking spaces, since we want to display the number in our label “Spaces available: X”.
For the Book parking button add the following code below the Patch code.
Notice that we have ended the code with a ; this means that we can now add additional code that runs after the patch.
Set(varNumberOfBookings,
CountRows(
Filter(Parking, BookedDate=DatePicker1.SelectedDate)
)
)
I always prefix my variable names with var since I struggle to remember names.
When I need to use a variable I start typing var and Power apps list all the variables I have created
Note that we get a delegation warning (indicated by yellow lines) suggesting that code might not work on large datasets.
It would be more suitable to create a Collection but we will save that for another time.
However we could write something like the following:
ClearCollect(
FilteredBookings,
Filter(
Parking,
BookedDate = DatePicker1.SelectedDate
)
);
Set(
varNumberOfBookings,
CountRows(FilteredBookings)
);
In the code, we set the variable varNumberOfBookings to count the number of rows returned from our Parking SharePoint list.
The rows returned are filtered based on the selected date in our DatePicker
Now we can go back to our label Spaces available and insert the variable:
"Spaces available: " & 4 -varNumberOfBookings
In this case, we want to show a negative number, so we substract 4 from our variable.
But it is not only when the user clicks the ‘Book parking’ button we want to update the number of rows.
It should also be done when:
- The app is loaded (App: OnStart) (You can run the “OnStart” command by right clicking App)
- The user removes a booking (Trashcan - OnSelect)
- The user changes the date (DatePicker1 - OnChange)
Insert the code in the 3 above functions
Run you app and change the date, add or remove a booking and see how the Spaces available changes.
Maximum 4 bookings
When a user interacts with our app, we now always update how many spaces are available.
To avoid more than 4 bookings on a specific date, we want to disable our “Book parking” button.
The button should also be disabled in case the user has already booked a parking space at the same date.
If(
varNumberOfBookings >= 4 ||
CountRows(
Filter(
Parking,
BookedBy.DisplayName = User().FullName, BookedDate = DatePicker1.SelectedDate
)
) >= 1 || DatePicker1.SelectedDate < Today(),
DisplayMode.Disabled,
DisplayMode.Edit
)
We are constructing an if statement that specifies if our variable is greater than or equal to 4 or (||) if the logged-in user is included in the rows returned, then the Book Parking button should be disabled.
While our app might not be production ready, and needs a design makeover, we now have a functional app
Here are some ideas how you could improve the app and challenge yourself
- Design it the way you like it - Maybe use the new modern components?
- Remove the delegation warnings
- Disable the book parking button if the user selects a date before Today()
- Add a tooltip or a label explaining the user why the button is disabled