Create a form dynamically with Power Automate
Terho Antila wrote an absolutely amazing blog post in 2021. It presents a solution that uses Power Automate as a simple web server. Unauthenticated users can fill out a dynamically generated form on the public network using a Power Automate workflow. Another Power Automate workflow then processes the responses submitted using the form.
Terho’s solution used adaptive cards . This time, we’ll build a similar solution as a simple HTML form without adaptive cards. My HTML and JavaScript skills have gotten rusty, so I’ll use Microsoft’s Copilot to help me with them.
Example – Collecting feedback from events
We want to build a solution that allows anonymous users to leave feedback about an event. The feedback asks
- Overall rating of the event
- Free comment on the event
- Rating for each session at the event
Feedback needs to be targeted to a specific event. In addition, events have different speakers, so their feedback forms always have different content.
Sounds complicated. MS Forms doesn’t support this. So how does Power Automate support this?
Data storage – SharePoint
Information about events and their sessions is stored in SharePoint lists, as well as related feedback.
Events
In addition to the name and date, a secret is stored for events. The secret is included in the feedback links and is used to determine which event the user is giving feedback on.
In addition, a Feedback form is saved for the event. We will return to it later.
Event feedbacks
General feedback given about the event is saved in its own list (Event feedbacks). The columns of the list are
- Event ID
- Overall rate
- Feedback
Sessions
The event sessions can be found in their own list. They are recorded with the title, speaker(s), and event identifier (EventID).
Session feedbacks
Feedback on sessions is simple. Only the rating and the session identifier (Session ID) are recorded.
Workflows (cloud flow)
Our future solution is roughly as follows:
- The user clicks a link that starts a Power Automate workflow (handle user request)
- The workflow returns the event feedback form corresponding to the link
- The user fills out the form and submits it
- The second workflow (handle user response) receives the submitted form data and saves it
Let’s start by creating workflows so that they have URLs.
Flow – Handle user request
Both workflows are started by the When an HTTP request is received trigger.
Allow anyone to call the flow. The method of the flow that responds to clicking a link is GET.
An address is generated for the flow when it is first saved.
Flow – Handle user response
Let’s create another flow. This one will process the user’s response. It will use the same tricks, but now using the POST method.
Web form
Next, let’s create a simple HTML form for the feedback survey. Or let Copilot create it for us. Let’s start with the following prompt.
Can you create a web form that is used by mobile phone. Form has 6 rows. Each row has header and then one input field with own header
Copilot responds promptly.
The result looks pretty decent in the browser for a first attempt.
Let’s ask the copilot to make a few more corrections.
Nice! Can you make input field little bit narrower (it will contain two digits). And field header should be on the left side of input field. not at the top of it.
Better.
One last touch.
Ok. can you add general header text on the beginning of the form? And after that two inputfields: Rate of the events (number) and then feedback for the event (multiline text)
The body of the form is complete.
When the user presses the submit button, the information filled in the form should be forwarded to cloud flow for processing.
How on earth is this done? Copilot knows, so we ask it to make the necessary changes.
Thanks. When user submits the form the content should be passed to the endpoint https://prod-254.westeurope.logic.azure.com:443/workflows/d8736f9c22a44246-... in JSON format.
After the submit we show "Your submit is processed..." text for the user. When we got response from the endpoint, we show the response to the user.
We get another HTML form in response. Let’s try to send it.
Submitting the form fails.
The reason is that the flow that processes the submitted form does not send a return response to the form. But it does receive the submitted form! The call contains all the information we entered into the form.
We now have the elements of a solution in place. However, it is not ready yet.
Creating an event-specific feedback form
Create a workflow that generates a separate form for each event and saves its HTML code to a SharePoint list. The pre-generated form is much faster to return to the user when they open the link.
Let’s start by searching for all events and going through the sessions for each event.
On the form, the feedback line for one session looks like this.
<div class="row">
<div class="row-header">Row 4</div>
<div>
<label for="field4">Field 4</label>
<input type="number" id="field4" name="field4" required>
</div>
</div>
We want to create such a HTML block for each event session on the form. For each session, we add a separate row to the variable (Session row). We name the field with the prefix 3 (=feedback from the session) and the session identifier (Id). This will make it easier to process the form in the future.
Add the event title and feedback fields regarding the event and sessions to the form (Compose – Create html form).
The completed form is saved in the event item.
Opening the feedback form
We will send event attendees a link where they can provide feedback. The link is the trigger link for the Handle user request flow.
The link is appended with the event’s secret as a parameter. This way we know which event the feedback is being provided for.
The final link looks like this:
https://prod-130.westeurope.logic.azure.com/workflows/69c8624a6104466aa...&event=P7Q8R9S0T1U2V3W4X5Y6Z7A8B9C0D1E2
What happens when a user clicks on the link?
Yes, the Handle user request flow will start. Let’s modify it a little.
First, we retrieve the event information that matches the parameter in the link (Get items – Matching event).
The events are filtered as follows:
Filter Query: Secret eq '@{last(split(last(split(triggerOutputs()['headers']?['X-WAWS-Unencoded-URL'],'&')),'='))}'
After this, the user is returned an HTML form created in advance for the event.
Body: @{First(outputs('Get_items_-_Matching_event')?['body/value'])?['Feedbackform']}
This way, when the user clicks on the link, they will be taken to the event-specific feedback form.
Saving feedback
Of course, we want to save the feedback that has been sent. This is done with the Handle User Response flow. The responses will already be there nicely.
The content of the response line (”1-1″:”5” etc.) is always this: “feedback type – feedback target”: “feedback”. The feedback types are as follows
- Event rating
- Free feedback on the event
- Speech-specific grades
The feedback target is essentially the row ID of the SharePoint list.
A table is created from the responses, which can be reviewed using the Apply to each function.
split(replace(replace(string(triggerBody()),'}',''),'{','') ,',')
We can access the different parts of the line with the following formulas.
Palautteen tyyppi = int(split(replace(first(Split(item(),':')),'"',''),'-')[0])
Palautteen kohde = split(replace(first(Split(item(),':')),'"',''),'-')[1]
Palaute = replace(last(Split(item(),':')),'"','')
Using these formulas, it’s easy to save feedback. Just remember to convert the grades to numbers (int()) before saving.
After saving the feedback, a message is sent to the HTML form stating that the saving was successful.
To the user, a successful submission looks like this.
Let’s ask Copilot to modify the HTML form so that after a successful submission, the form is hidden from view. Let’s make the changes received from Copilot into the workflow that we use to create the feedback forms.
After this, the form will look like this after the response.
Summary
So we’ve built a solution using Power Automate and SharePoint that can dynamically generate different forms for anonymous users. The responses are neatly stored in SharePoint lists.
I think the idea of using the Power Automate Response function to return an HTML page to the user is brilliant. Not mine, though.
The solution does have its weaknesses, of course. Power Automate is slow. When a user clicks on the feedback link, it takes a while for the form to open. This can be significantly speeded up by creating the forms in advance, as we did this time. Feedback processing also takes time, meaning the user has to wait a while to receive confirmation of successful submission.
The solution requires that Power Automate can be triggered by anyone on the Internet. Of course, you need to know the URL, but that’s it.