Teams + Power Apps: Building context/theme aware apps

By default, for any Power Apps canvas app used on Teams, either using Dataverse for teams, or a Standalone canvas app (added as Teams Tenant app or a tab) there is a list of parameters/context variables that Teams passes to the app via QueryString that can be used to detect current Teams context:

  • locale
  • channelId
  • channelType
  • chatId
  • groupId
  • hostClientType
  • subEntityId
  • teamId
  • teamType
  • theme
  • userTeamRole

By using those parameters it’s possible to create theme aware apps and even list data related to the context the app is installed, such as Team settings, members of a Microsoft 365 group (from the team where it is installed), list of channels and Planner plans and tasks, as in the example below:

Using Dataverse for Teams to build the app, you would have an additional option that is to use the native Teams integration object that already comes with every app. However bear in mind that to properly use this some manipulation will be needed as the context values are not exposed immediately when the app starts, the default behaviour has a slight delay for the data to be available.

In this post, I will show how to get the context using an approach that works for either Dataverse for Teams or Standalone Canvas Apps added to Teams.

How to get the parameters in the app

To get any QueryString parameter on canvas apps, we need to use the formula Param. For example, to get the current Teams group ID, we can call Param(“groupId”). This parameter is passed only to apps used as team apps. Personal apps will have the groupId as blank always. So, for all examples mentioned in this post, we are targeting apps installed as tabs in Teams teams.

So to use all retrieved data across the app in an easier way, we can assign some values during the app OnStart event to global variables and reference them on the places we need.

Before starting to manipulate the context values, add the ‘Microsoft Teams’ connection to your app:

On the OnStart event, add the following formula:

With(
    {
        tmpGroupID: Param("groupId"),        
        tmpTheme:Param("theme")
    },
    If(
        !IsBlank(tmpGroupID),
        Set(
            appConfig,
            {
                Theme: {
                    FontColour: If(
                        tmpTheme = "dark",
                        White,
                        tmpTheme = "contrast",
                        Yellow,
                        Black
                    ),
                    BackgroundColour: If(
                        tmpTheme = "dark",
                        RGBA(31, 31, 31, 1),
                        tmpTheme = "contrast",
                        Black,
                        RGBA(245, 245, 245, 1)
                    ),
                    ButtonColour: If(
                        Teams.Theme.Name = "dark",
                        White,
                        RGBA(98,100, 167,1)
                    )
                },
                TeamsData: {
                    GroupId: tmpGroupID,                   
                    TeamSettings: MicrosoftTeams.GetTeam(tmpGroupID),                                      
                    TeamRole: Switch(
                        Param("userTeamRole"),
                        "0",
                        "Owner",
                        "Member"
                    ),
                    UserDevice: Param("hostClientType")
                }
            }
        )))
 

This formula will create a global variable named appConfig, which consists of a JSON object with the Teams properties to be used across the app:

Theme: Calculated values for font colours and background colours based on the Teams context. On this example, I have already extracted the Microsoft Teams exact colours according to each theme to make it easier and look as a native app.

TeamsData: Data related to the current team, obtained using the ‘Microsoft Teams’ connector + some parameters passed from Teams context.

How to use the variables created on the app OnStart event

For any label used in the app, for the Color property, instead of using a manually set colour, reference the variables configured on the app start:

appConfig.Theme.FontColour

For all the screens in the app, for the Fill property, instead of using a manually set colour, reference the variables configured on the app start:

appConfig.Theme.BackgroundColour

Also in this example, to make the app look nicer, for all the galleries a background using the Teams default purple colour and a bit of transparency is used (last parameter on the RGBA value).

The appConfig variable is not used here because the transparency will have effect regardless of the theme used (here we also highlight the selected item in the gallery):

If(
    !ThisItem.IsSelected,
    RGBA(98,100,167,0.1),
    RGBA(98,100,167,0.3)
)

Set the gallery Fill to Transparent, so only the TemplateFill colour will appear.

For the app header, the principle is the same, we can use a rectangle as the background where the Fill, HoverFill and PressedFill are set to the teams purple colour with some transparency:

RGBA(98, 100, 167, 0.3)

Getting Planner Plans and Tasks, Microsoft Teams team members and Channels list

Before using the context values in Planner / Groups, add the Office 365 Groups and Planner connections to the app:

To list all planner plans for the Team where the app is installed in a gallery, you can use the following formula as the items property:

If(
    !IsBlank(appConfig.TeamsData.GroupId),
    Planner.ListGroupPlans(appConfig.TeamsData.GroupId).value
)

Rename the gallery to galPlanner. And for the gallery where you want to use the Planner tasks, use the following formula (using the V3 as it’s the latest version of the action to list tasks):

If(
    !IsBlank(appConfig.TeamsData.GroupId) && !IsBlank(galPlanner.Selected.id),
    Planner.ListTasksV3(
        galPlanner.Selected.id,
        appConfig.TeamsData.GroupId
    ).value
)

To retrieve the Planner tasks, we need to use the Group ID for the team and the Plan ID as in the formula above.

To retrieve the Team members in a gallery, you can use the following formula as the items property:

If(
    !IsBlank(appConfig.TeamsData.GroupId),    
         Office365Groups.ListGroupMembers(appConfig.TeamsData.GroupId).value       
)

To retrieve the Team channels in a gallery, you can use the following formula as the items property:

If(
    !IsBlank(appConfig.TeamsData.GroupId),
    MicrosoftTeams.GetChannelsForGroup(appConfig.TeamsData.GroupId).value
)

Teams settings detection

Another interesting usage would be detecting the Teams settings based on the current Team, so the behaviour of the app could change according to the Teams settings. Based on the Teams data detected using the Microsoft Teams connector and global variable initiated on the app start values, there are a lot of settings exposed that you could use, such as Guest settings, Fun settings, member settings.

For example, you could use the following syntax to detect if custom memes are allowed:

appConfig.TeamsData.TeamSettings.funSettings.allowCustomMemes

Or the following to detect if guests are allowed to create and update channels:

appConfig.TeamsData.TeamSettings.guestSettings.allowCreateUpdateChannels

In this post’s example we use the giphy settings to show a different icon according to the settings. In the emoji icon, the Icon property is set to:

If(
    appConfig.TeamsData.TeamSettings.funSettings.allowGiphy,
    Icon.EmojiSmile,
    Icon.EmojiSad
)

Results

By tweaking your Power App using the context, you can quickly enable your app to detect data related to the Teams team where it is installed and also make it theme aware. Below some examples applying the approach explained above and the values gathered on the app OnStart event (note the background, font and gallery colours changing on each):

App installed in a Team with default theme, with giphy settings set to not allow giphy (sad emoji):

App installed in a Team with Dark theme, with giphy settings set to not allow giphy (sad emoji):

App installed in a Team with Contrast theme, with giphy settings set to not allow giphy (sad emoji):

App installed in a Team with default theme, giphy settings set to allow giphy (smile emoji) – note that in this example, the plans, tasks and members also differ as it is installed on a different team:

An app screen detecting some Teams team settings:

Conclusion

By using the Teams context and a few tricks, we are able to make a canvas app look similar to the native Microsoft Teams look and feel and detect/manipulate data related to the Team where it is installed.

On this example it’s mentioned only listing data from Planner, Groups and Teams, but using the same connectors and context it is also possible to do several additional actions, such as: create Planner tasks, send messages to Teams and create Teams channels, just using the default Power Apps connectors.

5 comments

  1. Hello,

    Great blog post, just wondering, in Teams you can add a SharePoint list as a tab. Now if someone used the “integrate > Power Apps > Customize forms” option, can the same thing be done to that form when it gets loaded in Microsoft Teams?

    Thank you 🙂

  2. Hi Daniel,

    Thanks 😁

    As far as I am aware there is no way to use the params function (which you would need to retrieve the team id and other parameters) directly in the SharePoint form accessing it using the default integration (opening it from the list view)…

    This approach would work for Standalone canvas apps and apps built using Dataverse for Teams….

  3. Hi,

    I initialized a global variable in the app OnStart with the groupId and used this value in a drop-down box with Planner.ListGroupPlans on another screen. This works and shows the correct plans however upon app start up in Teams and also whilst editing the app and error is thrown up stating invalid value for parameter ‘groupId’.

    Some others also have the same issue and we aren’t sure why it is occurring.

    Could you help?

    1. Hi Todd,

      Are you using by any chance ‘Use non blocking Start Rule’ in your app settings? This could be causing the issue as you might try to use the value before it’s assigned.
      Also whenever you load data from planner, add some logic to see if the Id is not blank first….
      Example:

      If(
      !IsBlank(appConfig.TeamsData.GroupId),
      Planner.ListGroupPlans(appConfig.TeamsData.GroupId).value
      )

      If you want to test the values in the editor, you would need to maybe create a hidden screen with a button that sets the id variables manually and runs the same action as on the app start event, as in the Power Apps studio you cannot access Query String parameters…

Leave a Reply

Your email address will not be published. Required fields are marked *