Canvas app UI element: tag box & list

I love opportunities to create “new” UI elements for a canvas app. Recently, I came up with the idea of creating a list of text values of variable size with the ability to easily remove items from the list. This could be useful when you want to add tags in a record or create some related records to a main record without filling in all fields immediately. You could also use this to have a variable amount of filters that you want to apply to a data source.

Since the concept I had in mind reminded me of when you filter items in a webshop based on tags, I called it a “tag box & list” component.

Desired behavior

The behavior that I want to achieve is relatively simple. In a text input control, I want to type my input and when submitting, it should be added to a list below the text box. I don’t want duplicate values in the list and I want to be able to easily remove items from the list.

Since I’m thinking about UI, I want this to look good as well.

Controls

To build this, we need a couple of controls:

  • Text input
  • 2 buttons
  • Gallery, with inside
    • Label
    • Button
    • “Cancel” icon

The button inside the gallery will just be used for background of the item, so make sure it is at the bottom of the control hierarchy inside the gallery. In the below screenshots you can see the controls (I have renamed them to a descriptive name already).

Screenshot of the Power Apps control hierarchy indicating where the background button is in the tree.

Organize the controls as in the below screenshot (or a variation on it that best fits your application. Add the text “Add” to one of the buttons and “Clear” to the other. Of course you can style the controls according to your color scheme. I have made the “Clear” button gray so there is a distinction with the primary button to “Add” an item into the list below.

Screenshot of the organized controls in the canvas app

Basic logic

💡 In the function code, make sure to replace control and collection names with the names you are using.

o achieve the behavior described above, we’ll be working with a collection that is visualized inside the gallery. Items will be added to the collection using the text box (and “Add button”). To remove an item from the collection, the user presses the cancel icon inside the gallery, and the “Clear” button can be used to clear the collection with one click.

First thing to do is creating the collection by adding items into it. When a user presses the “Add” button we want to add whatever text is in the textbox to the collection. So, in the OnSelect property of the “Add” button, add the following code:

Collect(
        colText,
        txtTagToAdd.Text
    )

Clearing the collection is done by adding another piece of code into the OnSelect property of the “Clear” button.

Clear(colText)

To remove one item from the collection, add the following code into the “Cancel” icon’s OnSelect.

RemoveIf(colText,Value=ThisItem.Value)

Now we have defined the collection, and we can visualize it inside the gallery. Add the collection, in my case colText, in the Items property of the gallery. Next, set the Text property of the label inside the gallery to:

ThisItem.Value

You can now already test the tag box, and the basic functionality is complete: you can add tags into the list, remove one item from the list or clear the list completely.

The cherry on top

Now, there is some additional logic or functionality that I want to add.

  1. The text box should automatically clear after adding a value into the list
  2. Duplicate values should not be allowed
  3. The “Add” button should only be active when the textbox is not empty
1. Automatically clearing the textbox

To automatically clear the textbox, we’re going to introduce a local variable that will be used as the Reset property of the textbox control.

In the “Add” button’s OnSelect property, add two extra lines to your function so it becomes the following:

Collect(
    colText,
    txtTagToAdd.Text
);
UpdateContext({locClearTextInput: true});
UpdateContext({locClearTextInput: false})

And set the Reset property of the textbox to

locClearTextInput

This ensures that the textbox will reset after the item is added into the collection.

2. Don’t allow duplicate values

When a user tries to add a duplicate value into the list, I want to display a warning and not add the item into the list. I don’t want to clear the textbox in this case, since it might be that they want two very similar items in their list.

To get this behavior, we will add onto the code we already have in the OnSelect property of the “Add” button – it’s really where all the magic happens. 😉 The complete function will be:

If(
    txtTagToAdd.Text in colText,
    Notify(
        "The item is already in the list, please try again with a different value.",
        NotificationType.Warning
    ),
    Collect(
        colText,
        txtTagToAdd.Text
    );
    UpdateContext({locClearTextInput: true});
    UpdateContext({locClearTextInput: false})
);

This checks to see if the text that is currently in the textbox is already in the list. If this is the case, a warning is displayed. Otherwise, the item is added and the textbox cleared, just as before. Below you can see what the warning looks like.

Screenshot of the warning "The item is already in the list, please try again with a different value'.
3. Deactivate the “Add” button when relevant

It doesn’t make sense to me to add empty items in the list, so I want to deactivate the “Add” button when the textbox is empty. This is possible by changing the DisplayMode property of the button to the following:

If(IsBlank(txtTagToAdd.Text),DisplayMode.Disabled,DisplayMode.Edit)

The result

You can see the resulting behavior in the below clip. The tag box behaves as expected: adding and removing items to and from the list is possible, there is a check for duplicates, and it’s not possible to add empty items in the list.

Clip of the resulting UI element, adding some items, trying to add duplicates, removing items from the list and clearing the list.

If you want to set this up even more quickly and/or experiment with it, I have uploaded an canvas app containing just this setup to my github here.

Dynamically fill in a SharePoint multi-select person field using Power Automate

Multi-select person fields in SharePoint are quite common, but not straightforward to fill in using Power Automate when you have a variable number of people that could be added. In this post, I’m sharing a way that you can achieve this!

Identifying how to provide the data

To understand how this works, we first need to look at how SharePoint builds up a multi-select person field. For this, add a SharePoint “create item” action with a list that has a multi-select person field defined in it. (You can also use “update item” or “update file properties”) Then, where the multi-select person field is added, enter two dummy inputs by clicking “Add new item” below the first dropdown and providing some data. After entering the data, click the “T” icon in the top right corner of the field to switch to inputting the entire array, and there you’ll see the format of the array that is passed to SharePoint.

Click the “T” button to switch to input the entire array
The data that was entered will be transformed to the right format

This is the format that we need to provide the data in: an array (in between the square brackets) with objects (in between the curly brockets) that specify the “Claims” field, containing an email-address in between double quotes.

Creating an array

The easiest way to create an array in Power Automate is working with an array variable, and the “Append to array” built-in action. So to start, at the beginning of the flow, initialize a variable of type array and provide it with a meaningful name – in my case “CollaboratorsArray” since I will be adding a group of collaborators in an item in a list. Don’t supply an initial value.

Adding the necessary data to the array

Depending on where you’re getting the input email-addresses from, these steps will differ slightly. The basic idea is that for each emailaddress you want to add into the array, you have an “Append to array variable” action that will add an additional object to the array. You can do this with separate actions after each other if you want to combine multiple inputs into one, or you can do this inside a loop to add a list of emails.

In my case, I’m getting the emailaddresses that I want to add from a comma-separated string as a manual input from the flow. Therefore, I will need an “Apply to each” loop and will need to split the input string to get to the list of emailaddresses.

I’m first adding the “Apply to each” action to the flow, and adding the split function as the collection that the loop should iterate over. Afterwards, I add the “Append to array variable” action inside the loop and building up the object that needs to be supplied. So the value of your append action should have the following format:

{
   "Claims":"your value"
}

Providing the array to the SharePoint action

Now, all that’s left is to provide the array we built to the SharePoint action in the right location. To make this work, we should add the array into the right field in the “input entire array” option. This is the option where you don’t have the “Add new item” button.

The result will look like the image below. This will correctly fill the multi-select person field in SharePoint, and works when the number of people that are added can be different each time the flow is called!

Create a no-code button with icon (part 2)

A couple of months ago, I shared how you can create a button for navigation with an icon in a component and match its behavior to that of the “normal” buttons in canvas apps in this blog post. Back then, buttons created in this way could only be used for one specific action (in my case, navigating to another screen).

Since Power Apps added behavior properties to its canvas components, we can now extend this component solution so that a click on the button can trigger any function you want! Isn’t that cool? Let’s see how we can do this.

I’ll be starting from the button I created in that previous blog post. If you want to (re-)read that first, click this link.

⚠ If you’ve created the button component in a component library and are using it in applications, make sure that you make changes in a copy of the component, otherwise your other apps could stop working.

💡While this functionality is in preview, make sure to turn it on in the settings of your app or component library.

It’s quite easy to change the button so it can trigger any function when selected. Three steps is all it takes.

Step 1: Delete the “Screen” input property

Because we will change the component so it can trigger any function when selected, we don’t need the dedicated “Screen” property anymore. Therefore, we can simply delete it from the component. This will add an error to the component. Don’t worry about that for now, we’ll fix that in step 3.

Step 2: Add an “OnSelect” behavior property

Add a new custom property to the component and name it “OnSelect”. By choosing “OnSelect”, it will be straightforward for people familiar with canvas apps what they can expect this property to do. All controls that can be selected have this property defined, so it will be recognizable. The configuration is shown in the image below.

  1. Delete the “Screen” input property from the component
  2. Add an “OnSelect” behavior property to the component
  3. Trigger the “OnSelect” of the component when clicking the top button inside the component

Step 3: Configure the component to trigger OnSelect

The final step is to make sure that when the top button inside our component is clicked, this triggers the OnSelect property of the component itself. This is done by referencing the component’s OnSelect property in the OnSelect property of the top button.

Select the top button in your screen or from the tree view in the app studio and choose the OnSelect property from the property dropdown.

You’ll see that the function in the OnSelect property is still referencing the Screen property we deleted in the first step. This is why we’re getting an error. Replace the function in the function bar to simply reference the component’s OnSelect property as follows:

ComponentName.OnSelect()

As a result, the error has disappeared, and we can now invoke any function we want when clicking the button inside our app by configuring the OnSelect property after we’ve added the button component.

Bonus: this is just like the standard buttons canvas apps provides, which makes it an intuitive solution, and you can offer this component to be used by beginning Makers without much risk.

With this new functionality, we’re not limited to navigation anymore, we can use it to patch data to a data source, show or hide controls on our app, etc. The possibilities are endless!

2020: a year in review

At the beginning of a new year, I like to reflect on what the past year has brought to learn and plan for the upcoming year so that I can start it on my terms.

2020 was an eventful year, to say the least. I believe no one was expecting it or prepared for it, I know I wasn’t. Just like everyone else, I tried to make the best of it. And just like everyone else, I had my ups-and-downs. So what did 2020 look like?

Community

2020 was definitely the year that I started to be more active in the community.

In the beginning of the year, I started this blog. Even though I did not blog as consistent as I initially planned, I’m proud of the blog posts that I did publish. More importantly, I’m excited to continue blogging! That really is the main outcome I was aiming for. As I wrote in my very first blog post, I had tried blogging before and had given up, which I didn’t want to happen this time around. Of course, the universe threw some curveballs and there are some gaps. Despite this, I’m here in the beginning of 2021 and still blogging. And I already have some ideas I’m working on!

Just like I started blogging, I started speaking at conferences this year as well. I was fortunate enough to get the opportunity to speak at 2 live events before I was confined to the comfort of my own home indefinitely. Special thanks to Power Platform Saturday Warsaw 🇵🇱 for being the first ever conference I got the chance to speak at! I had some more events lined up that were cancelled and of course several of the organizers decided to move the event online. This resulted in 5 speaking engagements in total. A good start, and I’m eager for more. I’ve already got 2 events lined up for the first 2 months of the year, let’s hope more are added. And dare I hope for an in-person event towards the end of the year?

Personal

The theme for 2020 was courage. Stepping out of my comfort zone, trying new things and daring to question myself and my beliefs.

On the one hand, I had a lot of time for introspection because I had nowhere else to be but home. On the other hand, I found that the lockdown took away a lot of my energy and motivation. As an introvert, this was surprising since I get energy from being alone. I believe the uncertainty of when things will go back to “normal” is the main reason my energy level was down. It’s still challenging sometimes, and something I’m working on by trying to find stability and certainty in myself, instead of outside factors. It’s a journey…

Possibly the biggest surprise of 2020 was that in April I started running. And when I say started, I mean started from zero. My first run I averaged 7’52” for one kilometre. I followed a “start to run” plan and after 10 weeks I could run 30 mins straight. I was so proud of myself! To this day, I’m still running 3 times per week, and am on my way to running 10k. I never thought I’d say these words: I’m a runner. If nothing else, 2020 has made me a runner.

Not a picture of me, just to be clear

Some trivia

I read 13 books in 2020. Most memorable are Daring Greatly by Brené Brown and Good Morning, Good Life by Amy Landino. During my summer vacation, I took a trip down memory lane and teenage/young-adult nostalgia and re-read the entire Twilight series. I’m currently reading Sapiens by Yuval Noah Harari, also a recommendation if you want to gain some perspective on what we as humans have done in the time we’ve been on this planet.

We spent 1 week in the summer and the week between Christmas and New Year’s painting the majority of the house. Only two rooms left: my home office (picking colors isn’t easy!) and the guest bathroom downstairs. We plan on tackling those last two sometime in the next year.

I’ve picked up a new hobby in the last month: knitting. Completed projects are a headband, a blanket for our dog to lie in front of the pellet stove, a hat for my sister-in-law (Christmas present) and for my boyfriend. Currently working on a sweater for the dog. I’ve been looking for something creative to do in my spare time and knitting is fitting that gap nicely currently. Time will tell if it’s a keeper.

Looking ahead

2021 will come with its own set of challenges, opportunities and learnings. The theme for the year will be action. I spend too much time thinking (mostly doubting and second-guessing) and want to turn that into action. One of my guiding quotes is:

The only things you’ll regret in life are the things you didn’t do

I’ve started reading The Daily Stoic by Ryan Holiday. It’s a one-page-a-day book from which I want to get a daily piece of wisdom on the three principles of Stoïcism: control your perceptions, direct your actions properly and accept what is outside of your control. Three things that will help me in living according to my theme of the year.

On the professional side, I will continue to blog and speak at conferences (if they’ll have me 😊). Other than that, I’m working on something together with a community rockstar, that I hope we will be able to share with the rest of the community in the coming months. Stay tuned for that…

All that’s left is for me to wish you, from the bottom of my heart, a very happy and healthy 2021!

Expand and collapse rows in a Power Apps canvas app gallery

Galleries are one of the core components of Power Apps canvas apps, and there are many ways in which you can use them. Most often, they are used to show a list of information and give the user the option to click through to get even more information about the record or to take action.

In these cases, I’ve found it’s often difficult to decide what information to put in the gallery, and which to put in the detail screen. You need to balance the need for information with the screen estate and not having information overload. Therefore, it can be useful to show some basic information at first and giving the option to show some additional information by expanding the item before clicking through to the detail screen.

The result will look like this:

How can you create this? Let’s take a look…

Setting up the gallery

A gallery in which one item is expanded while the others are collapsed is in essence a gallery where different rows can have a different height. Therefore, you need to use a “flexible height gallery”. In other types of galleries, you cannot get to the same behaviour as you have in the example above.

Therefore, let’s start by adding a “Blank flexible height” gallery to the screen.

You can resize it so it fits your application. In my case it’s taking up the entire screen. Add the data source for the gallery and the controls that you need to show the information, including that which you only want to show when the item is expanded. You’ll notice that apart from the first row (which is the template cell), the height of all rows will adjust automatically when adding an extra control and moving it below ones that are already there. This is the main function of the flexible height gallery, and what we will use to create the expand/collapse effect: the height of each row adjusts to what is present in that row.

After adding the data, let’s add a down and up arrow icon to the gallery. They should be at the same X and Y coordinates, so they replace each other when collapsing/expanding. In my gallery, I’ve added a “more info” label and navigation icon as well so it’s clear when a user selects it, that they will go to another screen with more information. Also, I’ve added a line at the bottom of the gallery (which is a rectangle with tiny height) to indicate the different rows in the gallery.

Adding the collapse/expand functionality

What we want to achieve is that when a row is collapsed (which is default for the entire gallery), a user only sees the down arrow and can press it to show some additional information for this row (in my case the phone number and birthday).

When a row is expanded, the down arrow is replaced by the upwards arrow. This can be clicked by the user to collapse the row again and hide the additional information.

To make this functionality work, there are three things that need to be done:

  1. When selecting the “down” arrow, update a local variable “locInfoExpanded” to “true” and when selecting the “up” arrow, update a local variable “locInfoExpanded” to “false”.
  2. Set the “Visible” properties of the additional information, up and down arrow so they are visible at the right time
  3. (only when you have a separator between gallery rows) Change the Y position of the separator so it moves down when the row is expanded and up when it is collapsed

Arrow configuration

In the “OnSelect” property of the down arrow icon, add the following code:

Select(Parent); UpdateContext({locInfoExpanded:true})

In the “OnSelect” property of the up arrow icon, add the following code:

Select(Parent); UpdateContext({locInfoExpanded:false})

Visible properties

The “Visible” property of the additional information and the up arrow should be adapted to the following:

ThisItem.IsSelected && locInfoExpanded

Alternatively, that of the down arrow should be the opposite:

! (ThisItem.IsSelected && locInfoExpanded)

This ensures that the down arrow is shown for all rows that are not selected and for the selected one only if it is not expanded. If the arrows are placed at the same X and Y coordinates (and have the same height and width), it will seem as if they replace each other.

💡 Note: you can use just one icon control and dynamically change the displayed icon and executed functions as well by using if-clauses in the “Icon” and “OnSelect” property of the icon control.

Position of the separator

The position of the separator should change with the visibility of the additional information. More specifically: when the additional information is not visible, it should be placed right underneath the last visible item (in my case the address). When the row is expanded, the separator should be at the bottom (in my case right underneath the birthday.

To make it simple, I’m using the visibility of the birthday value label to determine where the separator should be placed instead of using the “Visible” formula.

The Y position of the separator should be set as follows:

If(
    nameOfLastLabelInExpandedSection.Visible,
    nameOfLastLabelInExpandedSection.Y + nameOfLastLabelInExpandedSection.Height + 2,
    nameOfLastLabelInCollapsedSection.Y + nameOfLastLabelInCollapsedSection.Height + 2
)

Which translates to the following in my case:

If(
    lblBirthdayKey.Visible,
    lblBirthdayKey.Y + lblBirthdayKey.Height + 2,
    lblAddressKey.Y + lblAddressKey.Height + 2
)

The result

That’s it, you’ve built a gallery in which individual rows can be expanded to show additional information! This is what is should look like:

Using JSON to optimize Power Automate input parameters in the Power Apps trigger

This blog post is part of a 3-part series:

  1. Understanding default naming for Power Automate input parameters in the Power Apps trigger
  2. A uniform approach to Power Automate input parameters in the Power Apps trigger
  3. Using JSON to optimize Power Automate input parameters in the Power Apps trigger (this post)

In the previous two posts I published, I described how input parameters for the Power Apps trigger are created in a Power Automate flow and a solution to provide uniform naming for all input parameters in the flow. However, this is not a flexible solution. It can present inconveniences when adding an additional input parameter, or changing the setup of your flow where a certain input parameter is used in a different context.

In this blog post, which is the last in this series, I want to share an approach to input parameters that allows a lot of flexibility in the number and names of input variables: using JSON as input in the flow.

The method

Instead of creating an input parameter for all of the inputs that I need in the flow, I’m going to create one input parameter of type text. This input parameter will contain a JSON object (passed as a string), which will have fields for each of the desired inputs. What does that look like?

First, I’m going to add an “Initialize variable” action immediately after the trigger in my flow. This will be a variable of type string with the name “Inputs”. Just as in my previous blog post, I’m renaming the action to the name of the variable and then adding the “Ask in PowerApps” dynamic content. This will create an input parameter for the flow called “Inputs_Value”.

PowerApps 
Inputs 
Name 
Inputs 
Type 
String 
Value 
Insert a dynamic value 
Dynamic Value 
Search content from previous steps 
PowerApps 
Ask i n PowerApps 
o 
x 
Learn more

This variable will be a JSON object. To get the contents of the JSON object, I’m adding a “Parse JSON” action after my variable initialization. The content to parse will be the variable that I created. I’m generating a schema by providing a sample JSON object that represents the input parameters I want to provide in my flow. Taking the same example variables as in the previous blog posts, this is the sample schema I’m adding into my flow:

{
    "ItemId": 1,
    "ItemTitle": "Title",
    "EmailSubject": "Subject of the email"
} 
Insert a sample JSON Payload 
Clicking 'Done' will overwrite your current schema 
"Itemld": I 
"ItemTitIe" : 
"Title" , 
"EmailSubject": "Subject of the email" 
x 
Done

The schema is generated automatically. If I now add another action into the flow, my input parameters will be available as outputs of the parse action.

Send an email (V2) 
O 
Carmen Ysewijn X 
Su bject 
Insert a dynamic value 
Dynamic Value 
p Search content from previous steps 
Parse JSON 
Item Id 
Item T it Le 
EmailSubject 
o 
x 
Learn more

If I add this flow into a Power Apps canvas app, there is only one text input variable needed, as you can see below.

uny• . Noscasued

The good and the bad

As mentioned before, this approach provides a lot of flexibility. If I need to remove an input, I remove it from the schema and don’t provide it in my app anymore. It will not still linger and be an extra input that I need to provide a value for even though it isn’t used anymore.

Adding an input is also relatively easy: I change the schema by adding a field and provide the extra input as part of the JSON string created in the app. This will have no impact on the trigger (it still expects one input parameter), and will not require me to remove and re-add the flow input my app before it works.

The main downside of this method is that if someone else is building the app and they are not aware that the input string should be JSON or which fields are expected exactly, they will not be helped by the hint in Power Apps studio. You can’t provide the correct inputs without having knowledge of the flow, or it being clearly documented somewhere.

Next to flexibility, another advantage of this method is that the trigger is completely separated from the logic in the flow. (The same goes for the approach using variables for each of the inputs described in my previous post.)  If you want to change the trigger of the flow to a different trigger (for example a manual trigger to be used as a run-only child flow with owner-provided connections), you don’t have to replace the input parameters everywhere in the logic of the flow. You only have to replace it once in the “Initialize variable” action. Every reference to that variable will remain intact, sparing a lot of work.

I believe this approach to input parameters provides a lot of flexibility that is currently missing for Power Apps triggered flows. Given good documentation, it can enable you to always have the right input variables available in your flow, without risks of breaking it or the app(s) it is used in when things change.

A uniform approach to Power Automate input parameters in the Power Apps trigger

This blog post is part of a 3-part series:

  1. Understanding default naming for Power Automate input parameters in the Power Apps trigger
  2. A uniform approach to Power Automate input parameters in the Power Apps trigger (this post)
  3. Using JSON to optimize Power Automate input parameters in the Power Apps trigger

In my previous blog post, I explained how Power Apps trigger input parameter names are generated based on the name of the action and the field it is used in. Since there are some drawbacks to the variety of names that are created this way, I want to share a uniform approach that I often use when working with a fixed set of input variables that I know is highly unlikely to change in the future.

The method

We know that an input parameter is generated using 2 parameters:

  1. The name of the action it is generated in
  2. The name of the field it is generated in

We can only control the first part, so to have a uniform naming, we should use one action that can generate different types of parameters within the same field. That action is “Initialize variable“. Using the “Type” field, you can differentiate between different types of parameters that can be passed by a Power Apps canvas app. The second part of the input parameter name will always be _Value (since this is the field that we generate the parameter in). You can then control the first part of your input parameter name by renaming the action before you generate the input parameter. That way, you have a uniform naming convention. Let’s take the same example parameters as in the previous blog post.

For the subject of the email and the title of the item we want to create, we can create a string parameter, for the ID we’ll use an integer. After adding three “Initialize variable” actions, filling in the name and type of the variable, we need to take two actions to create our input parameters for the flow:

  1. Rename the “Initialize variable” action to the name of the variable
  2. Add the “Ask in PowerApps” dynamic content in the initial value


The resulting input parameters will now have a name according to the following pattern: VariableName_Value. A uniform approach to input variables!

Itemld 
Name 
Itemld 
Value 
Itemld V 」 x 
ItemTitle 
Name 
ItemTitle 
String 
Value 
ItemTitle Valu x 
EmailSubject 
Name 
EmailSubject 
String 
Value 
EmailSubject Value x

The good and the bad

The great thing about using this approach is that all your input variables will show up using the same pattern in your app. When adding this flow to a Power Apps canvas app it’s easy to know what is expected in each of the input parameters thanks to these names.

Run(ltemld_Value, ItemTitle_Value, EmailSubject_Velue) 
Variableinputvariables . Runl

However, this is not a flexible solution. If tomorrow it is decided that the email is replaced by an approval, the input variable will still be called EmailSubject_Value. Or if the parameter is not used anymore in the flow, it will still be present and required as input parameter. When adding a new input parameter in your flow, you could have to remove and add the flow again in order to ensure that the changes on the trigger are picked up and your app doesn’t break.

Therefore, in the next and final blog post in this series I’m offering a flexible solution that addresses both these issues: Using JSON to optimize Power Automate input parameters in the Power Apps trigger.

Understanding default naming for Power Automate input parameters in the Power Apps trigger

This blog post is part of a 3-part series:

  1. Understanding default naming for Power Automate input parameters in the Power Apps trigger (this post)
  2. A uniform approach to Power Automate input parameters in the Power Apps trigger
  3. Using JSON to optimize Power Automate input parameters in the Power Apps trigger

When you’re using a Power Apps trigger in a Power Automate flow, the names of input parameters are generated automatically. Additionally, once you’ve created an input parameter, it’s impossible to rename it or even remove it when it’s not needed or used anymore.

In this series, I’m starting by explaining the pattern of the name that is generated for these input parameters. In the next blog posts, I’m looking at other ways of creating and generating these input parameters: a uniform approach and one that provides more flexibility afterwards.

How are input parameter names generated?

Power Automate input variables are automatically generated for the Power Apps trigger when you choose the “Ask in PowerApps” dynamic content in any of the actions in your flow. In the below example, I’m choosing this dynamic content in the “Id” field of the SharePoint “Get item” action.

PowerApps 
Get item 
Site Address * 
List Name * 
Questions 
Insert a dynamic value 
Dynamic Value 
Search content from previous steps 
1119k 
o 
x 
Learn more
Get item 
Site Address • 
List Name • 
Questions 
lcf •

This will create an input parameter with the name “Getitem_Id”. As you can see, the name that is being generated is the name of the action without the spaces, followed by an underscore and the name of the field in the action, also without spaces.

Some more examples below:

Create item 
Site Address • 
List Name • 
Questions 
Createitem_TitIe X 
Send an email (V2) 
To • 
O 
Carmen Ysewijn X 
Subject •

Sounds good, no?

There are a few things to consider. As soon as the input parameter is generated, it will be saved in your flow. If you remove it from the action, it will remain present in the trigger and therefore you’ll need to specify it when you’re calling this flow in a canvas app. If you rename the action, the input parameter will not be renamed.

Depending on whether you rename your actions or not, these names can also be too generic. Let’s say you have two “create item” actions in your flow. How will you differentiate between the input variables without looking at the flow each time? Or what about when you’re not sending an email in the flow anymore but switched to an approval and the variable is still called “Sendanemail(V2)_Subject”?

You can see why it could be a good idea to approach input parameters for Power Apps triggered flows in a different way. In the next two blog posts I’ll share two alternative approaches.

The first one is using a uniform approach to name input parameters so they are more meaningful: A uniform approach to Power Automate input parameters in the Power Apps trigger.

In the other I’m going a step further and providing a way to gain more flexibility so you’re not stuck with an input parameter when you don’t use it anymore: Using JSON to optimize Power Automate input parameters in the Power Apps trigger.

Creating document sets using a custom Canvas Apps SharePoint form

The problem

As you probably know, it’s very easy to customize the standard SharePoint form for a list or library using Power Apps. However, if you’re working with document sets it’s not as easy. Well, it’s just as easy to create the custom form. What’s currently not possible out of the box is to choose any document set content type using the content type field of the SharePoint form. In this post I share a solution using Power Automate that does allow you to create a document set from a Power Apps customized SharePoint form without using any code.

💡 We start with a document library in SharePoint that has a document set content type already added to it.

Solution: Power Automate

Create a new Instant flow in the default environment of your tenant. It has to be in the default environment since otherwise you won’t be able to add it into the customized form later on. Choose Power Apps as the trigger for the flow.

Add an Initialize variable action for all metadata that you need to create the document set. In my case that’s Name , Description, Status, Deadline and Size. Make sure to choose an appropriate type for the types of variables that you’re working with.

💡 I’m renaming my actions to the name of the variable so the input variables have a clear name when adding the flow to my canvas app later on.

Add Ask in PowerApps as dynamic content in each of the variables you’ve created so that they become input parameters for your flow.

The next steps is where the magic happens. I always think of document sets as “folders with metadata” and introduce them to customers as such. Also, if you sync libraries that have document sets in them using OneDrive sync, document sets show up as folders in your file explorer. This lead me to conclude that you can create a document set using two steps:

  1. Create a folder in the library
  2. Change the content type of the created folder to that of the document set

To create a folder, add the Create new folder action to your flow. Fill in the parameters for the library and choose the Name variable as folder name. Next, add an Update file properties action. Fill in the library parameters and in the Id, add the Id of the folder that was created in the previous step.

Now you’ll notice that the document set content type is not available in the Content type Id dropdown. To change the content type to that of the document set, we need to get the Id from SharePoint and add it as a custom value into the Update file properties action. To get the content type Id, open the library settings in SharePoint and select the document set content type (to do this, “allow management of content types” needs to be turned on). When you have the library content type open, the content type Id will be at the end of the url after “&ctype=” (indicated in yellow in the below image). Copy everything after the equals sign and paste that into the Content type Id field as a custom value.

Now you can add the other variables as inputs for the corresponding metadata fields. Finally, save the flow. The resulting flow should look similar to the below image. Now we can customize the SharePoint form.

Solution: Power Apps

Open the document library for which you want to customize the form. Then choose Customize forms from the Power Apps dropdown in the menu bar. Power Apps will initialize your form with only the Title field present (which we actually don’t need). Start by adding all other fields you want users to fill to the form, leave the Title field in there as well. We’ll customize it to show the Name field instead.

Unlock the Title data card from the advanced properties and add Name into the DataField property of the data card. Change the label text to Name.

Now we need to make sure that the form behaves correctly both when creating and when editing the properties of the document set. Therefore, we need to make 3 additional changes.

1. Change the “OnSave” property of the SharePointIntegration

In the OnSave property of the SharePointIntegration, we need to make sure that the creation flow is called when creating a new document set. Since I have not created an edit flow I want to simply submit the form when editing the document set properties. If you have created an edit flow, make sure to add it into the second part of the formula.

To add the flow into the form, temporarily add a button control to the app and add your flow using the Action menu. (It cannot be added directly into the OnSave property.) After the flow has been added, you can delete the button and add the following formula into the OnSave property of the SharePointIntegration control. (Note that the name of the form in the below formula will be different if you renamed it in the Power App)

If(
		SharePointForm1.Mode = FormMode.New,
		// FormMode.New: Run the flow and reset the form
			YourFlowName.Run(InputProperty1, InputProperty2, ...); 
			ResetForm(SharePointForm1),
		// FormMode.Edit: Submit the form
			SubmitForm(SharePointForm1)
)

In my case, the OnSave property looks as follows:

2. Change the OnReset property of the SharePoint form control to RequestHide().

3. Change the DisplayMode property of the Title/Name data card value

When submitting an edit form, the customized form does not make any changes to the Name of the document set. Therefore, to avoid confusion with users wanting to change the name of the document set, I want to make sure that in edit mode the Name data card is not editable.

Add the following formula into the Name text input control’s DisplayMode property:

If(SharePointForm1.Mode=FormMode.Edit,DisplayMode.View,Parent.DisplayMode)

Result & considerations

The customized form is ready to be used and will work both when creating a new document set and when editing the properties of an existing one.

An important drawback of this approach is that saving the form when creating a new document set will not trigger a refresh of the SharePoint page. Users will have to do a manual refresh to see their newly created document set. Depending on the number of actions in your flow before creating the document set, the creation might take some time and the document set will not immediately show up.

If you’re working with multiple document set content types, you have to resolve the guid of the selected content type in order to create a document set with the right one. In this case, I have hardcoded the content type guid into my flow. It’s also possible to get the guid using a SharePoint HTTP call and resolving the required one based on the name. However, this takes some additional manipulations and would have led too far for this blog post.

Create a no-code navigation button with icon

In one of my current projects, we’re working on a canvas app where user experience is an essential part of the project. We teamed up with a designer to make sure that the app fits into the company’s styling guidelines and that the UI was as intuitive and attractive as possible. One of the elements present in the resulting design is a button with an icon on it in addition to the label.

In the standard button control, it’s not possible to add an icon. If we just added the icon on top of the button, the colors will differ when hovering over the button or the icon which is not ideal for user experience. Since we didn’t want to create a custom component with code to add the possibility of an icon, I created a button component using only standard controls.

The resulting button will look and behave like this:

Keep reading for the steps to create this button!

Button requirements

Buttons can be used for many different things in an app: submit a form, navigate to another screen, apply a filter to a gallery, etc. Typically, when a button is pressed, an action needs to happen. Since canvas components currently don’t support specifying actions as their inputs or outputs, we are limited in what we can do with a button component. In this project’s requirements, the buttons would be used to navigate to a different screen.

Creating the component

💡 It’s not required to create the button as a component, but I prefer to do this to have less controls in my actual app later on.

You can create the component in any canvas app you have or in a dedicated component library. After creating the component, I’m renaming it to btnNavWithIcon so it’s easily identifiable when I want to use it in my app. I’m also changing the height and width to a commonly used button shape and size.

I am then adding the four controls I need to create the button: the background button (btnBottom), a label (lblNavButton), a random icon (icnNavButton) and the top button (btnTop). The reason I’m adding two buttons is to make sure that the top button (which will be transparent) and background (which will have a color) will be exactly the same shape. At this point, it doesn’t matter where they are placed inside the screen since that will all be determined dynamically. What is important is that the top button control is in front so that that can actually be selected when the component is used in an app. We can see which control is at the front of the component in the Tree view (higher position in the tree = higher layer in the app/component).

I’m defining three custom input properties for my control:

  • Label (text): the label that will be visible in the final button
  • Icon (text): the icon that will be used
  • Screen (screen): the screen to navigate to when the button is pressed

The next thing to do is link these input properties to the controls in our component, remove the labels from the button controls and disable the bottom button.

  1. Set the “Text” property of lblNavButton to btnNavWithIcon.Label
  2. Set the ‘Icon” property of icnNavButton to btnNavWithIcon.Icon
  3. Set the “OnSelect” property of btnTop to Navigate(btnNavWithIcon.Screen, ScreenTransition.None)
  4. Set the “DisplayMode” property of btnBottom to DisplayMode.View
  5. Set the “Text” property of btnTop and btnBottom to “”

Let’s complete the basic functionality and styling of the button as well.

  1. Set the size of btnTop to the size of the component
  2. Set the “X” and “Y” properties of btnTop to 0
  3. Set “Height”, “Width”, “X” and “Y” of btnBottom to the corresponding properties of btnTop
  4. Resize and position the icon and label so they fit nicely inside the component
  5. Set “Fill” of btnTop to Transparent
  6. Set “HoverFill” of btnTop to RGBA(255,255,255,0.1) – This is 90% transparent white, meaning the color behind it will be about 10% lighter
  7. Set “PressedFill” of btnTop to RGBA(0,0,0,0.1) – This is 90% transparent black, meaning the color behind it will be about 10% darker

The last 3 properties will make it appear that the icon and label are part of one button, since their color will change together with the background color (the fill color of the bottom button).

The button will look like this:

💡 You can test the component by setting the input properties you defined using the formula bar. In this case, I’ve set “Icon” to Icon.Settings (without quotation marks) and “Label” to “Settings”.

Styling the button

To determine the styling of the button, there are plenty of options. You can fix colors, position and size of the icon and label inside the button, you can make their position and size dynamic based on the height and width of your component, or you can specify additional input properties so that whoever will use your component has control over it.

In my case, I’m choosing a dynamic styling based on user inputs. This means I need to add a couple more input properties for the location and size of my controls: IconLocation, IconSize and FontSize. I’m also adding two color input properties: ButtonFill and TextColor. For the IconLocation and IconSize, I’m specifying the possible values in the description: Top, Bottom, Left and Right for location and Small, Medium and Large for size.

To apply the styling on the controls, we first need to decide what we want the styling to be. Colors is easy, they will be defined when someone adds the control to their app. Apply the below settings to btnBottom, icnNavButton and lblNavButton.text

But what does “Top” or “Left” mean? And what size is “Large” compared to “Small”? I’m using the following definition:

  1. If the position of the icon is “Top” or “Bottom”, the label and icon will be centered inside the component
  2. Horizontal margins are 10% of the width of the control, vertical will be 10% of the height of the component
  3. “Small” means the icon’s height and width is 30% of the minimum of height and width of the component, “Medium” 50% and “Large” 70%
  4. Default position is “Left” and size “Medium”

Let’s break this down for the “X” property of the icon.

  1. If the position of the icon is “Top” or “Bottom”, the center of the icon should be in the center of the button. Using the below image, we can work out what that means in terms of known properties.
500
  1. If the position of the icon is left the margin compared to the left side of the button should be 10% of the width of the button. This translated directly to the X-coordinate of the icon.
  2. If the position of the icon is right, the margin compared to the right side of the button should be 10% of the width of the button. We can again use an image to figure out what this means in terms of known properties.

Bringing these three together, we get the following formula for the X-coordinate of the icon.

By not specifying “Left”, this will act as the default location of the icon and will also work if no or an incorrect value is specified.

Using similar reasoning and the styling rules defined, the remaining position and size properties of the icon and label can be specified.

Settings for the icon control
Settings for the label control

That’s it! The button component is now ready to be used!

The result

We can easily test the resulting component by changing the input properties using the formula bar. Changing height, width and icon position could yield the result in the following animation.

We have successfully created a button component with a label and an icon with a couple of styling options to make it flexible. If we add this button to an app and specify the “Screen” property we can navigate to that screen by pressing the button. In the below animation I have created a simple test app with 3 screens and some buttons to navigate between them.

I hope this helps in creating your own custom button component with an icon. Good luck!