Skip to content

Commit 3631ea2

Browse files
Merge pull request pnp#125 from wjamesw/dynamic-tag-gallery
Initial release of Dynamic Tag Gallery
2 parents 2e54dd3 + 0c9d5a8 commit 3631ea2

File tree

75 files changed

+29602
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+29602
-0
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# Dynamic Tag Gallery Component
2+
3+
## Summary
4+
5+
This Power App demonstrates a component displaying a gallery of hashtags detected automatically from text and which dynamically places the hashtags in buttons across rows depending on the width of each and the room available on the row.
6+
7+
![Component Demonstration Screen](assets/Screen1.png)
8+
9+
Kudos to Dave Wyatt for his implementation of this concept and for giving me the idea for this approach. Building on his version that uses a predetermined number of buttons within a container, my approach uses a gallery to create as many buttons as required dynamically. Please do read [Dave’s excellent blog](https://community.powerplatform.com/blogs/post/?postid=b3d4acb9-bfc6-ef11-b8e8-7c1e5267b708) first.
10+
11+
## Applies to
12+
13+
![Power Apps](https://img.shields.io/badge/Power%20Apps-Yes-green "Yes")
14+
![Power Automate](https://img.shields.io/badge/Power%20Automate-No-red "No")
15+
![Power BI](https://img.shields.io/badge/Power%20BI-No-red "No")
16+
![Power Pages](https://img.shields.io/badge/Power%20Pages-No-red "No")
17+
![Power Virtual Agents](https://img.shields.io/badge/Power%20Virtual%20Agents-No-red "No")
18+
![Dataverse](https://img.shields.io/badge/Dataverse-No-red "No")
19+
![AI Builder](https://img.shields.io/badge/AI%20Builder-No-red "No")
20+
![Custom Connectors](https://img.shields.io/badge/Custom%20Connectors-No-red "No")
21+
![Power Fx](https://img.shields.io/badge/Power%20Fx-Yes-green "Yes")
22+
23+
## Compatibility
24+
25+
![Premium License](https://img.shields.io/badge/Premium%20License-Not%20Required-red.svg "Premium license not required")
26+
27+
## Contributors
28+
29+
* [James Williams](https://github.com/wjamesw)
30+
31+
## Version history
32+
33+
Version|Date|Comments
34+
-------|----|--------
35+
1.0|Febrary 2nd, 2025|Initial release
36+
37+
## Prerequisites
38+
39+
None
40+
41+
## Minimal path to awesome
42+
43+
### Using the solution zip
44+
45+
* [Download](./solution/dynamic-tag-gallery.zip) the `.zip` from the `solution` folder
46+
* Within **Power Apps Studio**, import the solution `.zip` file using **Solutions** > **Import Solution** and select the `.zip` file you just downloaded.
47+
48+
### Using the source code
49+
50+
You can also use the [Power Apps CLI](https://docs.microsoft.com/powerapps/developer/data-platform/powerapps-cli) to pack the source code by following these steps:
51+
52+
* Clone the repository to a local drive
53+
* Pack the source files back into a solution `.zip` file:
54+
55+
```bash
56+
pac solution pack --zipfile pathtodestinationfile --folder pathtosourcefolder --processCanvasApps
57+
```
58+
59+
Making sure to replace `pathtosourcefolder` to point to the path to this sample's `sourcecode` folder, and `pathtodestinationfile` to point to the path of this solution's `.zip` file (located under the `solution` folder)
60+
* Within **Power Apps Studio**, import the solution `.zip` file using **Solutions** > **Import Solution** and select the `.zip` file you just packed.
61+
62+
### Use the component in your app
63+
64+
Open your target app and click the **Get more components** icon from the **Insert** tab. On the **Import components** pane, select **cptTagGallery** from the **Dynamic Tag Gallery Component Library** and then click **Import** to import the component into your target app.
65+
66+
Then select **cptTagGallery** from the **Library components** group on the **Insert** tab.
67+
68+
Set the **Input Text** property of the component instance to the text, or the source of the text, you want the component to analyse.
69+
70+
Set the **Button Padding** and **Button Margin** properties of the component instance, or leave these as their default values.
71+
72+
Add logic to your app to retrieve the **Output Tags** property from the component instance.
73+
74+
## Features
75+
76+
The component displays a gallery of hashtags detected automatically from text and which dynamically places the hashtags in buttons across rows depending on the width of each and the room available on the row.
77+
78+
This is done using a technique whereby the controls in the gallery all have their co-ordinates calculated dynamically using the whole space within the gallery, rather than just the usual row per item within the gallery. This technique can be used to create many interesting visuals.
79+
80+
The dynamic calculations take place predominantly within the OnReset function of the component.
81+
82+
The key to successfully aligning controls in a gallery space is ensuring that you compensate for the offset of (at least) one pixel, resulting from the Template Size property of the vertical gallery control, which can not be set to zero. Apart from that one issue, controls across items in a gallery do not have to stay within the bounds of their item's row.
83+
84+
This solution illustrates the following concepts:
85+
86+
* Power Apps components
87+
88+
## Help
89+
90+
We do not support samples, but this community is always willing to help, and we want to improve these samples. We use GitHub to track issues, which makes it easy for community members to volunteer their time and help resolve issues.
91+
92+
If you encounter any issues while using this sample, you can [create a new issue](https://github.com/pnp/powerapps-samples/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=bug-report.yml&sample=dynamic-tag-gallery&authors=@wjamesw&title=dynamic-tag-gallery%20-%20).
93+
94+
For questions regarding this sample, [create a new question](https://github.com/pnp/powerapps-samples/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=question.yml&sample=dynamic-tag-gallery&authors=@wjamesw&title=dynamic-tag-gallery%20-%20).
95+
96+
Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/powerapps-samples/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=suggestion.yml&sample=dynamic-tag-gallery&authors=@wjamesw&title=dynamic-tag-gallery%20-%20).
97+
98+
## Disclaimer
99+
100+
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
101+
102+
<img src="https://m365-visitor-stats.azurewebsites.net/powerplatform-samples/samples/dynamic-tag-gallery" aria-hidden="true" />
449 KB
Loading
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
[
2+
{
3+
"name": "pnp-powerplatform-samples-dynamic-tag-gallery",
4+
"source": "pnp",
5+
"title": "Dynamic Tag Gallery Component",
6+
"shortDescription": "This Power App demonstrates a component displaying a gallery of hashtags detected automatically from text and which dynamically places the hashtags in buttons across rows depending on the width of each and the room available on the row.",
7+
"url": "https://github.com/pnp/powerplatform-samples/tree/main/samples/dynamic-tag-gallery",
8+
"downloadUrl": "https://pnp.github.io/download-partial/?url=https://github.com/pnp/powerplatform-samples/tree/main/samples/dynamic-tag-gallery",
9+
"longDescription": [
10+
"This Power App demonstrates a component displaying a gallery of hashtags detected automatically from text and which dynamically places the hashtags in buttons across rows depending on the width of each and the room available on the row."
11+
],
12+
"creationDateTime": "2025-02-02",
13+
"updateDateTime": "2025-02-02",
14+
"products": [
15+
"Power Apps",
16+
"Power Fx"
17+
],
18+
"tags": [
19+
"Hashtag"
20+
],
21+
"categories": [
22+
"CANVAS",
23+
"COMPONENT-LIBRARY"
24+
],
25+
"metadata": [
26+
{
27+
"key": "POWERAPPS-EXPERIMENTAL",
28+
"value": "No"
29+
},
30+
{
31+
"key": "POWERAPPS-PREMIUM",
32+
"value": "No"
33+
},
34+
{
35+
"key": "POWERAPPS-ONPREM",
36+
"value": "No"
37+
},
38+
{
39+
"key": "POWERAPPS-CUSTOMCONNECTOR",
40+
"value": "No"
41+
}
42+
],
43+
"thumbnails": [
44+
{
45+
"type": "image",
46+
"order": 100,
47+
"url": "https://github.com/pnp/powerplatform-samples/raw/main/samples/dynamic-tag-gallery/assets/Screen1.png",
48+
"alt": "App preview"
49+
}
50+
],
51+
"authors": [
52+
{
53+
"gitHubAccount": "wjamesw",
54+
"pictureUrl": "https://github.com/wjamesw.png",
55+
"name": "James Williams"
56+
}
57+
],
58+
"references": [
59+
{
60+
"name": "Microsoft Power Platform documentation",
61+
"description": "Discover how to make the most of Microsoft Power Platform products with online training courses, docs, and videos covering product capabilities and how-to guides.",
62+
"url": "https://learn.microsoft.com/power-platform/"
63+
},
64+
{
65+
"name": "Components from Components - Dynamic Tags (by Dave Wyatt)",
66+
"description": "In this example we are going to build our own dynamics tags, an example is Power DevBox Shortcut, a Edge/Chrome Extension which creates custom tags to filter your environments by",
67+
"url": "https://community.powerplatform.com/blogs/post/?postid=b3d4acb9-bfc6-ef11-b8e8-7c1e5267b708"
68+
}
69+
]
70+
}
71+
]
143 KB
Binary file not shown.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# msbuild output directories
4+
/bin
5+
/obj
6+
7+
# MSBuild Binary and Structured Log
8+
*.binlog
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<PowerAppsTargetsPath>$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\PowerApps</PowerAppsTargetsPath>
5+
</PropertyGroup>
6+
7+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
8+
<Import Project="$(PowerAppsTargetsPath)\Microsoft.PowerApps.VisualStudio.Solution.props" Condition="Exists('$(PowerAppsTargetsPath)\Microsoft.PowerApps.VisualStudio.Solution.props')" />
9+
10+
<PropertyGroup>
11+
<ProjectGuid>fbea9f87-0fe7-48e6-bde7-d077726d7344</ProjectGuid>
12+
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
13+
<!--Remove TargetFramework when this is available in 16.1-->
14+
<TargetFramework>net462</TargetFramework>
15+
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
16+
<SolutionRootPath>src</SolutionRootPath>
17+
</PropertyGroup>
18+
19+
<!--
20+
Solution Packager overrides, un-comment to use: SolutionPackagerType (Managed, Unmanaged, Both)
21+
Solution Localization Control, if you want to enabled localization of your solution, un-comment SolutionPackageEnableLocalization and set the value to true. - Requires use of -loc flag on Solution Clone or Sync
22+
-->
23+
<!--
24+
<PropertyGroup>
25+
<SolutionPackageType>Managed</SolutionPackageType>
26+
<SolutionPackageEnableLocalization>false</SolutionPackageEnableLocalization>
27+
</PropertyGroup>
28+
-->
29+
30+
<ItemGroup>
31+
<PackageReference Include="Microsoft.PowerApps.MSBuild.Solution" Version="1.*" />
32+
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
33+
</ItemGroup>
34+
35+
<ItemGroup>
36+
<ExcludeDirectories Include="$(MSBuildThisFileDirectory)\.gitignore" />
37+
<ExcludeDirectories Include="$(MSBuildThisFileDirectory)\bin\**" />
38+
<ExcludeDirectories Include="$(MSBuildThisFileDirectory)\obj\**" />
39+
<ExcludeDirectories Include="$(MSBuildThisFileDirectory)\*.cdsproj" />
40+
<ExcludeDirectories Include="$(MSBuildThisFileDirectory)\*.cdsproj.user" />
41+
<ExcludeDirectories Include="$(MSBuildThisFileDirectory)\*.sln" />
42+
</ItemGroup>
43+
44+
<ItemGroup>
45+
<None Include="$(MSBuildThisFileDirectory)\**" Exclude="@(ExcludeDirectories)" />
46+
<Content Include="$(SolutionPackageZipFilePath)">
47+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
48+
</Content>
49+
</ItemGroup>
50+
51+
<Import Project="$(MSBuildToolsPath)\Microsoft.Common.targets" />
52+
<Import Project="$(PowerAppsTargetsPath)\Microsoft.PowerApps.VisualStudio.Solution.targets" Condition="Exists('$(PowerAppsTargetsPath)\Microsoft.PowerApps.VisualStudio.Solution.targets')" />
53+
54+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<CanvasApp xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
3+
<Name>crad7_dynamictaggallerycomponentlibrary_de9c6</Name>
4+
<AppVersion>2025-02-02T20:34:15Z</AppVersion>
5+
<Status>Ready</Status>
6+
<CreatedByClientVersion>3.25013.14.0</CreatedByClientVersion>
7+
<MinClientVersion>3.25013.14.0</MinClientVersion>
8+
<Tags>{"primaryDeviceWidth":"640","primaryDeviceHeight":"640","supportsPortrait":"true","supportsLandscape":"true","primaryFormFactor":"Phone","showStatusBar":"false","publisherVersion":"3.25013.14","minimumRequiredApiVersion":"2.2.0","hasComponent":"true","hasUnlockedComponent":"true","isUnifiedRootApp":"false"}</Tags>
9+
<IsCdsUpgraded>0</IsCdsUpgraded>
10+
<GalleryItemId xsi:nil="true"></GalleryItemId>
11+
<BackgroundColor>RGBA(251,101,60,1)</BackgroundColor>
12+
<DisplayName>Dynamic Tag Gallery Component Library</DisplayName>
13+
<Description xsi:nil="true"></Description>
14+
<CommitMessage xsi:nil="true"></CommitMessage>
15+
<Publisher xsi:nil="true"></Publisher>
16+
<AuthorizationReferences>[]</AuthorizationReferences>
17+
<ConnectionReferences>{}</ConnectionReferences>
18+
<DatabaseReferences>{}</DatabaseReferences>
19+
<AppComponents>[{"appComponentName":"a77fca6af24446eb8638a6b9a78dc07e","displayName":"cptTagGallery","appName":"59dc2f33-903f-4b07-b50c-aaadec9bb9a1","appVersion":"2025-02-02T20:34:15Z","appComponentLibraryLogicalName":"crad7_dynamictaggallerycomponentlibrary_de9c6","appDisplayName":"Dynamic Tag Gallery Component Library","environmentName":"6ca51c28-f05d-ee87-8afd-29fcc9ef7fad","owner":{"id":"cd350c02-a2b3-4e79-aa4d-c8260894d466","displayName":"James Williams","type":"User","tenantId":"bd78dee9-9abf-4401-b6d6-e142688c4654","userPrincipalName":"james@wjwdev.onmicrosoft.com"},"allowCustomization":true,"createdOn":"2025-02-02T20:34:19.162Z","lastModifiedOn":"2025-02-02T20:34:19.162Z","connectionReferences":{},"databaseReferences":{}}]</AppComponents>
20+
<AppComponentDependencies>[]</AppComponentDependencies>
21+
<CanConsumeAppPass>0</CanConsumeAppPass>
22+
<CanvasAppType>1</CanvasAppType>
23+
<BypassConsent>0</BypassConsent>
24+
<AdminControlBypassConsent>0</AdminControlBypassConsent>
25+
<EmbeddedApp xsi:nil="true"></EmbeddedApp>
26+
<IntroducedVersion>1.0</IntroducedVersion>
27+
<CdsDependencies>{"cdsdependencies":[]}</CdsDependencies>
28+
<IsCustomizable>1</IsCustomizable>
29+
<BackgroundImageUri>/CanvasApps/crad7_dynamictaggallerycomponentlibrary_de9c6_BackgroundImageUri</BackgroundImageUri>
30+
<DocumentUri>/CanvasApps/crad7_dynamictaggallerycomponentlibrary_de9c6_DocumentUri.msapp</DocumentUri>
31+
<AdditionalUris>
32+
<AdditionalUri>/CanvasApps/crad7_dynamictaggallerycomponentlibrary_de9c6_AdditionalUris0_identity.json</AdditionalUri>
33+
</AdditionalUris>
34+
</CanvasApp>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"__Version":"0.1","App":"924e520f-0486-4777-9cb2-45d7f6536c30","Test_7F478737223C4B69":"d93e89c5-a972-481f-b8a0-1828689cec0e","Host":"8ddf98ae-6e0e-4b82-b649-85cb0ed52810","Screen1":"b6023237-a598-4863-bd83-a32478a8f128","cptTagGallery":"f1283332-8a5e-43d6-afee-a55c5052fa68","VerticalContainer":"31ea1b05-64a0-43b2-90cd-0f2415bd9265","VerticalGallery":"ea952032-0109-480c-bb97-5c1bac430bda","galleryTemplate2_2":"2b3f3dcd-b982-4681-8abb-f923d5866871","ButtonCanvas":"54029025-f26f-4bf1-897c-4dc2903ebd1b"}

0 commit comments

Comments
 (0)