Build a Dynamic Form in Power Apps
Table of Contents
This post will cover the following steps:
- Connecting the UI metadata to the PowerApp
- Creating a dynamic UI and collecting user input
- Exporting user input to Power Automate
Preparation
To begin, we need to create our UI metadata. What is UI metadata? It is data that describes the UI. This could be UI text, the input type, min/max numbers for sliders, question/section numbers, combo box options and anything else that may be of value to you. The metadata comes from a data source in PowerApps. In this article, we’ll be using a SharePoint List but SQL, Azure, Excel Sheets, and other data sources will work too.
Note: It is important to be consistent when creating UI metadata because the Power App will be using this data in If statements and inconsistency will break the UI.
Import the UI Metadata
To begin, I’ve created a blank canvas app. Let’s import the UI metadata.
- Click the data tab on the left sidebar
- Click ‘Add data’ and select the data source containing the UI metadata
Screenshot of data source added to the PowerApp
Create UI Metadata Collection
Now that the data source is added to the PowerApp, let’s add it to a collection in the OnVisible function of our screen.
- Go back to the tree view tab on the left sidebar
- Select your screen and navigate to the OnVisible function
- Add the following code shown in the screenshot below
Screenshot of our UI metadata added to a collection
Code from screenshot above:
Refresh('UI Metadata List');
ClearCollect(UIMetadataCollection, 'UI Metadata List');
Create the User Input Collection
Before we jump into creating the dynamic UI, we need to create a collection that will keep track of user input.
- Select your screen and navigate to the OnVisible function
- Add the following code shown in the screenshot below
Screenshot of changing OnVisible function
Code from screenshot above:
Clear(UserInputCollection);
ForAll(
UIMetadataCollection,
If(ThisRecord.ui_type <> "label" && ThisRecord.ui_type <> "button",
Collect(
UserInputCollection,
{
ui_text: ThisRecord.ui_text,
user_input: "",
ui_type: ThisRecord.ui_type,
min_number: ThisRecord.min_number,
max_number: ThisRecord.max_number
}
)
)
);
Summary: All the UI metadata (labels, control types, etc) live outside of the canvas app. This gives us the ability to add, edit, or remove UI elements dynamically without changing anything in PowerApps. In this section we’ve connected the data source to our PowerApp and we’ve created a collection that will keep track of all user input in our dynamic form.
Create Dynamic UI
Now it’s time to jump into the main reason you’re here, the dynamic UI. This is where the magic really happens. First and foremost, let’s create a flexible gallery.
- Create a flexible gallery as shown in the screenshot below
Screenshot of blank flexible gallery
2. Change the items property to UIMetadataCollection (the collection that holds the UI metadata imported from the data source) as shown below
Screenshot assigning the items property to UIMetadataCollection
Note: Click the pencil in the top left corner of the gallery to insert UI elements.
Label
- Add a label to the flexible gallery
- Select the label element and navigate to the Text property
- Add the following code shown in the screenshot below
Note: If you don’t see any text show up, refresh your PowerApp screen (save your work first). Another option is to create a second screen, add a button, and use that button to navigate to the Dynamic Form Screen. We need to do this because the OnVisible function of our screen needs to be triggered.
Screenshot changing Text property
Text Input
- Add text input to the flexible gallery
- Select the text input element and navigate to the Visible property
- Add the following if statement shown in the screenshot below
Screenshot changing Visible property
Code from screenshot above:
If(ThisItem.ui_type = "text_input", true, false)
Date Picker
- Add date picker to the flexible gallery
- Select the date picker element and navigate to the Visible property
- Add the following if statement shown in the screenshot below
Screenshot changing Visible property
Code from screenshot above:
If(ThisItem.ui_type = "date_picker", true, false)
Slider
- Add slider to the flexible gallery
- Before we set visibility, change the Default, Min and Max properties as shown in the screenshot below
Screenshot changing the Default, Min, and Max properties
- Now let’s set the visibility property
- Select the slider element and navigate to the Visible property
- Add the following if statement shown in the screenshot below
Screenshot changing Visible property
If(ThisItem.ui_type = "slider", true, false)
Checkbox
- Add checkbox to the flexible gallery
- Before we set visibility, change the Text property as shown in the screenshot below
Screenshot changing Text property
- Now let’s set the visibility property
- Select the checkbox element and navigate to the Visible property
- Add the following if statement shown in the screenshot below
Screenshot changing Visible property
Code from screenshot above:
If(ThisItem.ui_type = "checkbox", true, false)
- For the last step, we will want to adjust our label so that it doesn’t display the text twice when a checkbox element is being displayed.
- Select the label element and navigate to the Visible property
- Add the following if statement shown in the screenshot below
Screenshot changing Visible property
Code from screenshot above:
If(ThisItem.ui_type = "checkbox", false, true)
Button
- Add button to the flexible gallery
- Select the button element and navigate to the Visible property
- Add the following if statement shown in the screenshot below
Screenshot changing Visible property
Code from screenshot above:
If(ThisItem.ui_type = "button", true, false)
Summary: You may be starting to see a pattern here. In this section we made certain elements visible if they matched the ui_type in the metadata table. I challenge you to follow the same steps for the rest of the items in your UI metadata table.
Collect User Input
So now that the dynamic UI is built, we need to keep track of user input. This is where the UserInputCollection will be used. We’ll be using Lookup and Patch functions found in PowerApps. Let’s jump right in!
Text Input
- Select the text input element and navigate to the OnChange function
- Add the following code shown in the screenshot below
Screenshot changing OnChange function
Code from screenshot above:
Patch(
UserInputCollection,
LookUp(
UserInputCollection,
ui_text = Label.Text
),
{
user_input: TextInput.Text
}
);
Date Picker
- Select the date picker element and navigate to the OnSelect function
- In the OnSelect function we will add a variable so that PowerApps does not call OnChange when it is initializing the gallery. Add the variable in the screenshot below
Screenshot changing OnSelect function
- Next, navigate to the OnChange function
- Add the following code shown in the screenshot below
Screenshot changing OnChange function
If(datePickerChange,
Set(datePickerChange, false);
Patch(
UserInputCollection,
LookUp(
UserInputCollection,
ui_text = Label.Text
),
{
user_input: Text(DatePicker.SelectedDate)
}
);
)
Slider
- Select the slider element and navigate to the OnSelect function
- In the OnSelect function we will add a variable so that PowerApps does not call OnChange when it’s initializing the gallery. Add the variable in the screenshot below
Screenshot changing OnSelect function
- Next, navigate to the OnChange function
- Add the following code shown in the screenshot below
Screenshot changing OnChange function
If(sliderChange,
Set(sliderChange, false);
Patch(
UserInputCollection,
LookUp(
UserInputCollection,
ui_text = Label.Text
),
{
user_input: Text(Slider.Value)
}
);
)
Checkbox
- Select the checkbox element and navigate to the ‘OnCheck’ and ‘OnUncheck’ functions
- Add the following code shown in the screenshot below to BOTH functions
Screenshot changing OnCheck & OnUncheck functions
Patch(
UserInputCollection,
LookUp(
UserInputCollection,
ui_text = Label.Text
),
{
user_input: Text(Checkbox.Value)
}
);
Summary: We now keep track of all user input within the dynamic form. My speculation on why this works is that PowerApps keeps track of what gallery element the user is interacting with. As a result, we can use the element’s information to update our UserInputCollection by calling Patch and doing a LookUp using the Label.Text.
Export User Input
For our last section, navigate to the button we created earlier in the article.
Add a Power Automate
- When you have selected the button, navigate to the Action tab at the top of the page
- Select Power Automate and click on Create a new flow as shown below
Screenshot of creating a new flow
- Select the flow you want and customize it as you see fit. I have selected a Power Apps Button flow, added a Compose step, and selected Ask in PowerApps as the input as shown in the screenshot below
2. When you are done creating the flow, go back to the PowerApp and select the flow as shown below
Screenshot of adding a new flow
Export User Input as JSON
When the flow has been added, the last step is passing the UserInputCollection to the flow in JSON format.
- Select the button element and navigate to the OnSelect function
- Add the following code shown in the screenshot below
Screenshot changing OnSelect function
PowerAppsbutton.Run(
JSON(
UserInputCollection,
IncludeBinaryData
)
);
Note: If you need additional help exporting user input, take a look at this article written by Reza Dorrani. One more note: You can export user data to something else besides JSON as shown in the article.
Now that we’re done, save your application and give it a spin! When you click submit, go to your Power Automate and see it run. You can also add, edit, or remove UI metadata and see the UI updated in the PowerApp (after a browser refresh or button navigation).
Here is a final walk-through of everything we’ve built:
Final Walkthrough GIF
Happy Coding and God Bless!
Comments
-
Build a Dynamic Form in Power Apps
I want to make such a form but is there an option where I can add one value and if there are two values then there should be another option to add another value so that the next value tab will open and so on?
*This post is locked for comments