Canviz

Power Apps Tree Control

We recently created a Power App with a complex tree view control. Because Power Apps does not provide an out of the box tree view control, we investigated different ways to build one.

There are several ways a tree view can be implemented in Power Apps. After investigating many approaches, we found these patterns work the best.

Nested flexible-height Gallery controls

In this approach we use 2 nested galleries corresponding to the parent and child node levels in the tree view. In this approach, the parent gallery must be a flexible-height gallery. The child gallery is a fixed-height gallery.

Here you can see what the data looks like in the collection bound to the parent Gallery control. This data comes from a CDS entity named Demo Objectives. You will see this entity name in subsequent sections in this article.

IdTitle
0001Create an Awesome Customer Experience
0002Delight our customers

Here you can see what the data looks like in the collection bound to the child Gallery control. This data comes from a CDS entity named Demo Key Results. You will see this entity name in subsequent sections in this article.

IdTitleObjective (Lookup)
0001Improve Net Promoter Score from X to Y.0001
0002Increase Repurchase Rate from X to Y.0001
0003Maintain Customer Acquisition cost under Y.0001
0004Reduce revenue churn (cancellation) from X% to Y%.0002
0005Increase Net Promoter Score from X to Y.0002
0006Improve average weekly visits per active user from X to Y.0002
0007Increase non-paid (organic) traffic to from X to Y.0002
0008Improve engagement (users that complete a full profile) from X to Y.0002

Here are the important parent gallery settings.

Property Name
Property ValueNotes
Items‘Demo Objectives’Bind parent collection.

Here are the important child gallery settings.

Property NameProperty ValueNotes
ItemsFilter([@’Demo Key Results’], Objective.Id = ThisItem.Id)Filter the child collection based on the parent id.
TemplateSize35Row height for each item.
TemplatePadding0Set padding to 0 to avoid potential scroll bar inside the child gallery.
HeightCountRows(galChildGallery.AllItems) * galChildGallery.TemplateHeightDynamic height for child gallery based on the items count.

Notes about this approach:

Single flexible-height Gallery control

In this approach we added Path, Level and Visible metadata columns to the tree view data source so we can organize the nested items by sorting by the Path. We then calculate the indent for each item with the Level, and expand/collapse the child items with the Path and Visible columns.

Here you can see what the data looks like in the collection bound to the Gallery control. Notice in our example here we added the metadata columns to the same sample data source as the previous example.

IdTitlePath Level Visible
0001 Create an Awesome Customer Experience 00010true
0001Improve Net Promoter Score from X to Y.0001.00011true
0002Increase Repurchase Rate from X to Y.0001.00021true
0003Maintain Customer Acquisition cost under Y.0001.00031true
0002Delight our customers00020true
0004Reduce revenue churn (cancellation) from X% to Y%.0002.00041true
0005Increase Net Promoter Score from X to Y.0002.00051true
0006Improve average weekly visits per active user from X to Y.0002.00061true
0007Increase non-paid (organic) traffic to from X to Y.0002.00071true
0008Improve engagement (users that complete a full profile) from X to Y.0002.00081true

It’s up to you where you store this data. You can store it directly in the source where your tree data comes from (a view in SQL server, a CDS Entity, etc.). Or, you can query the data for your tree from one place and the data for the path and level in another, then merge them into a single collection in the Power App. That’s up to you to decide what works best for your scenario.

To calculate the indent we use Level * [Step].

ClearCollect(
DemoKeyResultsExtended,
AddColumns(
'Demo Key Results',
"ParentId",
Objective.Id /* workaround to get the parent id first as the associated object could only be loaded in this way */
)
);

/* generate tree nodes hierarchy */
Clear(TreeNodes);
ForAll(
'Demo Objectives',
/* append level 0 nodes */
Collect(
TreeNodes,
{
Level: 0,
Path: Id,
Id: Id,
Title: Title,
Visible: true /* expand by default */
}
);
/* append level 1 nodes */
ForAll(
DemoKeyResultsExtended,
If(
ParentId = 'Demo Objectives'[@Id],
Collect(
TreeNodes,
{
Level: 1,
Path: ParentId & "." & Id,
Id: Id,
Title: Title,
Visible: true /* expand by default */
}
)
)
)
);

/* sort nodes by path */
ClearCollect(
TreeNodes,
Sort(
TreeNodes,
Path,
Ascending
)
);

To expand/collapse the items in the tree we compare the path prefix when the user clicks one of the images associated with a node in the tree, like this:

UpdateIf(
TreeNodes,
Path <> ThisItem.Path && StartsWith(
Path,
ThisItem.Path
),
{
Visible: !Visible
}
);

Notes:

Custom Power Apps PCF Control (TypeScript)

In this approach we made a PCF Control to read data from the data source and render the tree control.  

Notes:

Exit mobile version