Thursday, March 22, 2018

PowerApps: Display a SharePoint User's name in another text field

Some very basic things are just far too convoluted in the current iteration of PowerApps.  Displaying raw text values from lists is one of them.  Even worse, are displaying individual fields from a List of Records.  The most obvious and common problem is just listing the name of a user selected from a SharePoint list (or one/multiple users from the same list).  

This is the primary issue w/ PowerApps: things which you assume to just be simple are convoluted, while things you believe will take forever as just a few mouse clicks away.
Well, here's how to get that crap done w/ the least hassle required.  Not zero hassle, just the least.
It seems so simple...

SharePoint LookUp Use Case

The single most common use-case per basic PowerApps is linking to a SharePoint list.  This brings a particular problem into the mix which is:  SharePoint does not store users as single values.

Let's say you have an application where you want to select a particular project and want to display the user who is assigned to it.  For the initial data entry, you use the standard SharePoint tools to link your field to your domain lookup and everything seems so very simple.

However, even in its simplest form, SharePoint stores a single user as a record of information:

User
  • DisplayName
  • ID
  • Email
  • Favorite hot sauce
  • ...
When dealing w/ user information, 99% of the time the first thing we're after is just the DisplayName (admittedly following shortly thereafter by their Email).  We just want to show that one (or more) name(s) you selected in a field somewhere else.  

Things fall apart specifically when you want to display/review information in non-editable fields (e.g. labels, HTMLText, etc.).  This becomes a problem because by default, SharePoint stores this single User record as a table of records just in case you want to have it be a multi-select to allow for multiple users.  So you now have a multi-dimensional array you have to handle just to get a person's name.

Also, the concept of a "loop" in PowerApps doesn't exist.  That means you have to iterate through this manually -OR- use the ForAll() function (which can get complex - particularly if you are just looking to display a user's f'ing name!).

The answer (in this case) is to work w/ the following functions:  First, FirstN, Last.

As an example, let's say I have created a drop-down named MyDropDown that is linked to the full record of a SharePoint data source that contains many fields: 

MySharePointList
  • Title
  • CompleteByDate
  • User
  • ...
Among these fields, is one named User that holds a single user responsible for a particular task.  But again, even that single User field is itself a record of values.  So, as I mentioned previously, it is a nested record within a record like so:

MySharePointList
  • Title
  • CompleteByDate
  • User
    • DisplayName
    • ID
    • Email
    • ...
  • ...
And again, since SharePoint stores these in a record of Users (note the s), it actually is:

MySharePointList
  • Title
  • CompleteByDate
  • User(s)
    • User1
      • DisplayName
      • ID
      • Email
      • ...
    • User 2
      • DisplayName
      • ID
      • Email
      • ...
    • ...
  • ...
There is simply no way around it.  This is how SharePoint creates such fields.

Regardless, when the end-user changes values in MyDropDown, I want to select a particular project and have the person responsible's name appear in a nearby field.

In pseudo-code that means you need to:
  • get the first record from the list of records
  • get the value of the user's name from the first record
  • display it

The Solution

To cut to the chase, in PowerApps, change the value of the Text property of the display field to be:
  • First(MyDropDown.Selected.User).DisplayName
That would show the name of the user in question.  

Yes...this works.


NOTE: It is worth noting that this very similar line will throw an error: First(MyDropDown.Selected.User.DisplayName)

To peel it apart:

First(MyDropDown.Selected.User).DisplayName
  • Get the first item in the list
  • NOTE:  This is a record and not a single value because Users are collections of values in SharePoint.
First(MyDropDown.Selected.User).DisplayName
  • The name of the drop-down box control you created
First(MyDropDown.Selected.User).DisplayName
  • A pointer at the record which is currently selected in the drop down
First(MyDropDown.Selected.User).DisplayName
  • The name of the specific field we care about within the record 
First(MyDropDown.Selected.User).DisplayName
  • Worth repeating from above.  This returned a record and we now have to pick the field inside THAT record which we care about.
First(MyDropDown.Selected.User).DisplayName
  • The actual field you want to display (vs. Email, Status, etc.) that is included in the record we retrieved inside the parenthesis
NOTE:  For some fields you'll also need to reference the actual "Value" within that field which might look like First(X.Selected).Y.Value

As if that wasn't bad enough for something that should be dirt simple, this gets EXTREMELY messy for SharePoint lists that allow for >1 users to be selected.  You could wind up w/ something like:
  • First(MyDropDown.Selected.User).DisplayName.Value & If(CountA(SelectedTitle.DisplayName.Value)>1,", " & Last(FirstN(SelectedTitle.DisplayName,2)).Value) & If(CountA(SelectedTitle.DisplayName.Value)>2,", " & Last(FirstN(SelectedTitle.DisplayName,3)).Value)
And this only handles up to 3 user names.  You'd need to copy/paste those last two lines over and over until you'd hit whatever you dream the maximum to be.

In fact, this scenario is where the ForAll() function is better used.  I'll have to put in some notes on that (someday) on how you could do this, but you can read up on the documentation here.

This is the ultimate issue w/ PowerApps that you will run into time and again.  It is so very easy to do some crazy complex integrations, but doing basic things will drive you nuts.

Now try to have the <Enter> key slaved to a particular function on a screen or when editing a particular field.  I'll wait here...
  

No comments:

Post a Comment

Because some d-bag is throwing 'bot posts at my blog I've turned on full Moderation. If your comment doesn't show up immediately then that's why.