Power Apps - Canvas - Formula Bar Anatomy

Table of Contents 1. Introduction 2. Basic Structure App Values UDTs (User Defined Types) Tables UDFs (User-Defined Functions) Assets Styles 7. Conclusion 8. References 1. Introduction Code reusability is relatively simple in traditional programming. Concepts like DRY (Don't Repeat Yourself) have existed for a long time, but in Power Platform, this was only possible with considerable effort. Now, this reality has changed with improvements in the formula bar, and that's what we'll explore. As we add more elements to the formula bar, it becomes increasingly difficult to maintain consistency. That's why I've been organizing it in a specific way that I'd like to share with you. 2. Basic Structure App Values This section contains basic information about the application and global variables that will be used throughout the app. /*-----------------------------------------------App Values-----------------------------------------------*/ AppName = "Power Track"; AppVersion = "1.0.0.0"; AppUser = udfGetUserDetails(User().Email); // Environment Variables evjsTheme = LookUp('Environment Variable Values', 'Environment Variable Definition'.'Display Name' = "evjsTheme").Value; /*-----------------------------------------------App Values-----------------------------------------------*/ UDTs User Defined Types (UDTs) help structure complex data and improve typing in the application. /*-----------------------------------------------UDTs-----------------------------------------------*/ // Custom types to structure Office 365 user data tpUser := Type( { AccountEnabled: Boolean, BusinessPhones: [{Value: Text}], City: Text, CompanyName: Text, Country: Text, Department: Text, DisplayName: Text, GivenName: Text, Id: Text, JobTitle: Text, Mail: Text, MailNickname: Text, OfficeLocation: Text, PostalCode: Text, Surname: Text, TelephoneNumber: Text, UserPrincipalName: Text, mobilePhone: Text } ); // Custom type to structure the color theme tpThemePalette := Type( { palette: { themePrimary: Text, themeLighterAlt: Text, themeLighter: Text, themeLight: Text, themeTertiary: Text, themeSecondary: Text, themeDarkAlt: Text, themeDark: Text, themeDarker: Text, neutralLighterAlt: Text, neutralLighter: Text, neutralLight: Text, neutralQuaternaryAlt: Text, neutralQuaternary: Text, neutralTertiaryAlt: Text, neutralTertiary: Text, neutralSecondary: Text, neutralPrimaryAlt: Text, neutralPrimary: Text, neutralDark: Text, black: Text, white: Text } } ) ; /*-----------------------------------------------UDTs-----------------------------------------------*/ Tables This section contains static table definitions and logic for data manipulation. /*-----------------------------------------------Tables-----------------------------------------------*/ // Definition of static tables and data manipulation // Screen inventory and access control based on named formulas tbScreens = [     {ItemId: 1, ItemDisplayName: "Home", ItemScreen: Home} ]; // Table used for navigation components such as a tablist for example tbNavigation = [     {ItemId: 1, ItemDisplayName: "Home", Visible: true, ItemTargetScreen: LookUp(tbScreens, ItemId = 1).ItemScreen } ]; // Example of defining a table for use within the app /* tbFeedBack = ShowColumns([Table], 'Created By', //Person Standard Rating, //Number Message //Multiple Line of Text ) ; */ /*-----------------------------------------------Tables-----------------------------------------------*/ UDFs User-Defined Functions (UDFs) allow encapsulating reusable logic, making the code cleaner and easier to maintain. /*-----------------------------------------------UDFs-----------------------------------------------*/ // Reusable functions that simplify logic udfGetUserDetails(ParamSearch:Text):tpUser = If(!IsBlank(ParamSearch), First(Office365Users.SearchUserV2({searchTerm: ParamSearch}).value) ) ; udfConvertSvg(ParamSvgValue:Text):Text = "data:image/svg+xml;utf8, "&EncodeUrl(ParamSvgValue); /*-----------------------------------------------UDFs-----------------------------------------------*/ Assets In this section, icons and other visual elements used in the application are defined. /*-----------------------------------------------Assets-----------------------------------------------*/ // Definition of icons and v

Apr 16, 2025 - 14:26
 0
Power Apps - Canvas - Formula Bar Anatomy

Table of Contents

  • 1. Introduction
  • 2. Basic Structure
    • App Values
    • UDTs (User Defined Types)
    • Tables
    • UDFs (User-Defined Functions)
    • Assets
    • Styles
  • 7. Conclusion
  • 8. References

1. Introduction

Code reusability is relatively simple in traditional programming. Concepts like DRY (Don't Repeat Yourself) have existed for a long time, but in Power Platform, this was only possible with considerable effort. Now, this reality has changed with improvements in the formula bar, and that's what we'll explore.
As we add more elements to the formula bar, it becomes increasingly difficult to maintain consistency. That's why I've been organizing it in a specific way that I'd like to share with you.

2. Basic Structure

App Values

This section contains basic information about the application and global variables that will be used throughout the app.

/*-----------------------------------------------App Values-----------------------------------------------*/
AppName = "Power Track";
AppVersion = "1.0.0.0";
AppUser = udfGetUserDetails(User().Email);

// Environment Variables
evjsTheme = LookUp('Environment Variable Values', 'Environment Variable Definition'.'Display Name' = "evjsTheme").Value;
/*-----------------------------------------------App Values-----------------------------------------------*/

UDTs

User Defined Types (UDTs) help structure complex data and improve typing in the application.

/*-----------------------------------------------UDTs-----------------------------------------------*/
// Custom types to structure Office 365 user data
tpUser := Type(
    {
        AccountEnabled: Boolean,
        BusinessPhones: [{Value: Text}],
        City: Text,
        CompanyName: Text,
        Country: Text,
        Department: Text,
        DisplayName: Text,
        GivenName: Text,
        Id: Text,
        JobTitle: Text,
        Mail: Text,
        MailNickname: Text,
        OfficeLocation: Text,
        PostalCode: Text,
        Surname: Text,
        TelephoneNumber: Text,
        UserPrincipalName: Text,
        mobilePhone: Text
    }
);

// Custom type to structure the color theme
tpThemePalette := Type(
        {
            palette: {
                themePrimary: Text,
                themeLighterAlt: Text,
                themeLighter: Text,
                themeLight: Text,
                themeTertiary: Text,
                themeSecondary: Text,
                themeDarkAlt: Text,
                themeDark: Text,
                themeDarker: Text,
                neutralLighterAlt: Text,
                neutralLighter: Text,
                neutralLight: Text,
                neutralQuaternaryAlt: Text,
                neutralQuaternary: Text,
                neutralTertiaryAlt: Text,
                neutralTertiary: Text,
                neutralSecondary: Text,
                neutralPrimaryAlt: Text,
                neutralPrimary: Text,
                neutralDark: Text,
                black: Text,
                white: Text
            }
        }
    )
;
/*-----------------------------------------------UDTs-----------------------------------------------*/

Tables

This section contains static table definitions and logic for data manipulation.

/*-----------------------------------------------Tables-----------------------------------------------*/
// Definition of static tables and data manipulation

// Screen inventory and access control based on named formulas
tbScreens = [
    {ItemId: 1, ItemDisplayName: "Home", ItemScreen: Home}
];

// Table used for navigation components such as a tablist for example
tbNavigation = [
    {ItemId: 1, ItemDisplayName: "Home", Visible: true, ItemTargetScreen: LookUp(tbScreens, ItemId = 1).ItemScreen }
];

// Example of defining a table for use within the app
/*
tbFeedBack = ShowColumns([Table],
        'Created By', //Person Standard
        Rating, //Number
        Message //Multiple Line of Text
    )
;
*/
/*-----------------------------------------------Tables-----------------------------------------------*/

UDFs

User-Defined Functions (UDFs) allow encapsulating reusable logic, making the code cleaner and easier to maintain.

/*-----------------------------------------------UDFs-----------------------------------------------*/
// Reusable functions that simplify logic
udfGetUserDetails(ParamSearch:Text):tpUser =
    If(!IsBlank(ParamSearch),
        First(Office365Users.SearchUserV2({searchTerm: ParamSearch}).value)
    )
;

udfConvertSvg(ParamSvgValue:Text):Text = "data:image/svg+xml;utf8, "&EncodeUrl(ParamSvgValue);
/*-----------------------------------------------UDFs-----------------------------------------------*/

Assets

In this section, icons and other visual elements used in the application are defined.

/*-----------------------------------------------Assets-----------------------------------------------*/
// Definition of icons and visual elements

svgHomeIcon = $"";

// Another option here is to make the svg colors dynamic

svgHomeIconDynamic(ParamColor:Text):Text = $"";

//To use it is simple, in the image value of an image control you pass the following function udfConvertSvg(svgHomeIconDynamic("#000000"))
/*-----------------------------------------------Assets-----------------------------------------------*/

Styles

Here, visual definitions such as colors, fonts, and component styles are centralized.

/*-----------------------------------------------Style------------------------------------------------*/
// Standardized colors, fonts, and visual elements

// Application theme based on environment variable
Theme = AsType(ParseJSON(evjsTheme), tpThemePalette);

// Fonts
Fonts = {
    Bold        : "Sans Black",
    Semibold    : "Sans Medium",
    Normal      : "Sans",
    Lighter     : "Sans Light"
};

// Text colors
FontColors = {
    Active      : ColorValue("#000000"),  // Active, selected states - using neutralPrimary
    Primary     : ColorValue("#32ba23"),  // Titles, headers - using themePrimary
    Secondary   : ColorValue("#373737"),  // Secondary text, subtitles - using neutralSecondary
    Disabled    : ColorValue("#595959"),  // Disabled text - using neutralTertiary
    WarnLight   : ColorValue("#D11F1F")   // Error text - kept as is because there's no equivalent in the palette
};

//FontSettings
FontSettings = {
    H1: {
        Bold:    { Font: Fonts.Bold,   Size: 24, Lineheight: 1.3, Fontweight: FontWeight.Normal, Color: FontColors.Primary    },
        Normal:  { Font: Fonts.Normal, Size: 24, Lineheight: 1.3, Fontweight: FontWeight.Normal, Color: FontColors.Primary    },
        Lighter: { Font: Fonts.Normal, Size: 24, Lineheight: 1.3, Fontweight: FontWeight.Normal, Color: FontColors.Secondary  }
    },
    H2: {
        Bold:    { Font: Fonts.Bold,   Size: 18, Lineheight: 1.3, Fontweight: FontWeight.Normal, Color: FontColors.Primary    },
        Normal:  { Font: Fonts.Normal, Size: 18, Lineheight: 1.3, Fontweight: FontWeight.Normal, Color: FontColors.Primary    },
        Lighter: { Font: Fonts.Normal, Size: 18, Lineheight: 1.3, Fontweight: FontWeight.Normal, Color: FontColors.Secondary  }
    },
    H3: {
        Bold:    { Font: Fonts.Bold,   Size: 16, Lineheight: 1.3, Fontweight: FontWeight.Normal, Color: FontColors.Primary    },
        Normal:  { Font: Fonts.Normal, Size: 16, Lineheight: 1.3, Fontweight: FontWeight.Normal, Color: FontColors.Primary    },
        Lighter: { Font: Fonts.Normal, Size: 16, Lineheight: 1.3, Fontweight: FontWeight.Normal, Color: FontColors.Secondary  }
    }
    ...
};

// Component definition example
Components = {
    Button: {
        Primary: {
            AutoDisableOnSelect: false,
            BorderColor: RGBA(0,0,0,0),
            BorderThickness: 0,
            Color: ColorValue(Theme.palette.white),
            DisabledBorderColor: ColorValue(Theme.palette.neutralLighterAlt),
            DisabledColor: FontColors.Disabled,
            DisabledFill: ColorValue(Theme.palette.neutralLight),
            Fill: ColorValue(Theme.palette.themePrimary),
            FocusedBorderColor: RGBA(0,0,0,0),
            FocusedBorderThickness: 3,
            Font: FontSettings.P.Bold.Font,
            FontWeight: FontSettings.P.Bold.Fontweight,
            HoverBorderColor: RGBA(0,0,0,0),
            HoverColor: ColorValue(Theme.palette.white),
            HoverFill: ColorValue(Theme.palette.themeDark),
            PressedBorderColor: ColorValue(Theme.palette.neutralPrimary),
            PressedColor: ColorValue(Theme.palette.white),
            PressedFill: ColorValue(Theme.palette.themeDarker),
            RadiusBottomLeft: 5,
            RadiusBottomRight: 5,
            RadiusTopLeft: 5,
            RadiusTopRight: 5,
            Size: FontSettings.P.Bold.Size
        }
        //...
    }
};
/*-----------------------------------------------Style------------------------------------------------*/

7. Conclusion

In summary, the concepts applied here are old; there's nothing about reinventing the wheel, but for Power Apps, they are relatively new. In other words, we just need to apply what already works here too.

Note: The structure above is just how I organize my formula bar. You are free to organize it as you wish, but just a tip: if you want to create a UDF that uses a table, the UDF must be below the table, which is why I organize UDT > Table > UDF.

8. References