I use SharePoint managed metadata a lot these days, as it provides a really important function in allowing effective content tagging.
A little while back, the PowerApps team rolled out support for managed metadata. This made me a very happy consultant indeed because I was working on a project that made heavy use of it.
As a quick SharePoint managed metadata refresher, consider the example of a simple idea register. Below is a SharePoint list called IdeaRegister with 2 managed metadata columns called Audience (who the idea applies to) and Project Phase (what part of the project should this idea be done). My idea is to provide more icecream to hardworking people in Corporate Communications during the Risk and Design phases of the project.
This type of SharePoint list is now fully supported in PowerApps. We connect to this list as a data source and if we add an edit form to our app, we will get a default experience like the screen below. Our two managed metadata fields are rendered by default as combobox controls..
If we take a closer look at the second combobox, we can see that multi-valued managed metadata columns are fully supported which is great. What is also nice is if you wish to make a change, the control has a built-in search/refiner that helps you quickly find terms. In the example below I type in the letters "C" and "O" and the three matching terms are listed for me to choose...
But screen real-estate comes into play here. As per the above image, I picked "Construction". Now take a look at the screen. We can no longer see our tags. Instead we are told how many items were tagged and we have to click on the control to see what was tagged.
I found this default experience a bit unfriendly, so I set about coming up with an alternate way of doing it. First here is a screenshot of an alternative approach. You can see that I have opted for an approach that removed dropdowns altogether. When a user click the tag button, they are prompted to pick one or more tags via a pop-up dialog...
Add in new idea and click tagTag one or more rolesView all tagged roles
Not only does this method look friendlier than the default experience, it has some other advantages.
The approach is repeatable. Basically each time you click a tag button it is the same popup that appears, but it is able to handle the different managed metadata columns.
The approach is bandwidth efficient. It will require less connection to SharePoint and in fact can be used in an offline scenarios as well.
So how was it done? Fortunately I recorded a video entitled "Have more team cuddles (and some PowerApps UI tricks with Managed Metadata)" - which if I say so myself, has to be a PowerApps academy award nominee in the category of "coolest PowerApps video title ever".
In the video I delve into detail, but for the sake of keeping this article readable, I will just provide a high-level view on the tricks used...
Okay so in a nutshell I used the following tricks...
The (at the time of writing) undocumented function called Choices()
The Addcolumns() function
A Canvas control with 3 Datacards and a gallery
Some trickery with collections.
The Patch() function
The Choices() function is very useful. It basically allows you to retrieve all of the possible values from a column that has a discrete set of values. It takes a column from a connected data source as a parameter., In the example below, I used the managed metadata column named Audience and stored it in a variable called ChoiceList.
The data returned by this function is a table and the format depends on the type of column. For managed metadata columns we get columns called Label, Path, TermGuid, Value and WssId. Now the meaning behind these columns aren't that important for this article except to say that Label is the column that stores the term a user picks from.
So armed with this knowledge, we can grab the latest set of managed metadata terms from a data source on application startup and store it in a variable or a collection.
Next I need to track which terms a user has selected. If you look at my screenshots above the video, you can see that the app tracks tagged terms via changing their color. To do this, I had to add an extra column to the table returned by the Choices() function. This column tracks whether this tag was selected by the user. I used the AddColumns() function to do this...
AddColumns() takes multiple parameters. At a minimunm you specify 1) The collection or data source you want to add a column to, 2) The name of the new column and 3) the default value of the new column. In the screenshot above you can see that I have created two collections to store tags for Auduence and Project Phase. The additional column I named Selected with a default value of false. If we check out the AudienceTags collection, we can see the intended effect - a new column called Selected.
Next comes a bit that might seem countere intuitive. I want to have a screen pop up and ask the user to tag content. But I want to make a single tagging pop-up rather than make multiple screens for each managed metadata column. I did this by taking advantage of the ClearCollect() function.
In short, depending on which tag icon you click, I initialise a generic collection called TagList by making a copy of the tag collection I want to work with. The diagram below shows how each button initialises the taglist from the two different source collections...
That means we now have a collection of tags all ready to go and all we need now a tag selector UI. Rather than make a separate screen for this, I added a canvas control to my screen. (To do this, create a scrollable screen or cut and patse a canvas from such a screen.) I then added three data cards to the canvas and set their Fill property to a see-through grey color. I resized the middle data card to take up most of the screen. The net result is a nice overlay effect.
In the middle data card, I added a gallery, set the data source to the TagList collection and added some nice formatting to make it look pretty. I added a button to the gallery to display the tag because I like the rounded edges (buttons have a property to control roundness). I also threw in the built-in tag icon and the result was the following...
Next step is to record when a user select or de-selects a tag. I did this using the UpdateIf() function to change the value of the Selected column (remember I added that earlier). The function looks like this:
Now we need to show the user that the tag has been selected. We do this by making the fill property of the button conditional on the selected column being set to true. Now that we have a boolean column called Selected, I can test for ThisItem.Selected.
Here is the effect... You can click and unclick to your hearts content...
It was around this point that I also made the canvas conditionally visible. By default, the canvas is hidden and is only visible when a user clicks on one of the tag buttons. After tagging, the user either clicks the Done or Cancel buttons to hide the canvas again.
I did this by creating a variable variable called ShowCanvas and setting the Visible property of the Canvas to it.
The final thing I did was to modify the Done button. Recall that the canvas only works with a generic collection called TagList. Once a user has chosen their tags, we need to save TagList back to the original collection (Audience or Project Phase), so I added some conditional logic to the button to copy TagList contents back to the source collection.
Now all I need to do is save this data back to SharePoint. For this, we will use the patch() function. Now this command looks way worse than it actually is, and I strongly recommend any aspiring PowerAppers to get familiar with it. Here is my patch function...I have wired it to the OnSelect property of a submit icon as shown below:
The first parameter to Patch is the data source we want to write to, which in my case is the SharePoint list containing the managed metadata columns. Of interest is how I patched the Audience and ProjectPhase columns. I was able to simply send the collections straight back to SharePoint as a patch parameter. All I did was filter the collections to only send back those marked as selected...
Neat huh? In fact the SharePoint connector did not care about the additional Selected column either... it happily added the new idea to SharePoint as intended.
I hope this article gave you some ideas for your own approaches. I should note that this approach is not well suited to multi-level managed metadata term sets, but I have a solution for that too, which I hope to cover in a future article and video.