0% found this document useful (0 votes)
11 views23 pages

Power Apps Next Level

This Power Platform Guide by Nicolò Ferranti focuses on enhancing the development of Canvas Apps using User Defined Functions (UDFs), User Defined Types (UDTs), and effective state management strategies. It emphasizes the importance of structured coding practices to avoid inefficiencies and technical debt, while introducing modular design and centralized logic for improved maintainability. The guide also explores the use of components and enhanced properties to create scalable applications, ultimately promoting a more reliable user experience.

Uploaded by

aishvanv
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views23 pages

Power Apps Next Level

This Power Platform Guide by Nicolò Ferranti focuses on enhancing the development of Canvas Apps using User Defined Functions (UDFs), User Defined Types (UDTs), and effective state management strategies. It emphasizes the importance of structured coding practices to avoid inefficiencies and technical debt, while introducing modular design and centralized logic for improved maintainability. The guide also explores the use of components and enhanced properties to create scalable applications, ultimately promoting a more reliable user experience.

Uploaded by

aishvanv
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 23

Power Platform Guide

POWER APPS
CANVAS
NEXT LEVEL
Modern State Management with UDFs,
UDTs, and Advanced Components

A Power Platform Guide Written By


NICOLÒ FERRANTI
Introduction
Power Platform is continuously evolving, and with it, the development of
Canvas Apps is adopting an increasingly structured and sophisticated
approach.

It is crucial to understand that low-code development does not mean


avoiding coding altogether, but rather embracing a different way to build
applications.

Approaching Power Apps development as merely copying and pasting


controls without proper planning and architecture can lead to significant
inefficiencies, increased technical debt, and maintenance challenges.

This guide aims to demonstrate how User Defined Functions (UDFs) and
User Defined Types (UDTs) can serve as powerful tools to create
scalable, maintainable, and robust applications.

Additionally, we will explore how these capabilities contribute to a more


effective state management strategy, an essential pillar for modern,
centralized app design that enhances consistency.

Just so you know, the features we will cover in this document are
currently in preview or experimental stages, and this document is
intended for exploratory purposes only.

Before seeing everything in action, let’s establish a context to identify


common inefficiencies and antipatterns that may arise during the
development of a Canvas app.
Common Pitfalls
During the development of Power Apps Canvas applications, it is easy to
fall into structural inefficiencies caused by bad practices that undermine
maintainability, scalability, and overall performance.

Some of the most common issues are:


Copy-pasting logic across different screens, causing duplicated
behavior.
Repeating similar controls (like buttons, labels, or toggles) with only
minor differences, often due to a lack of modular design.
Repetitive expressions involving functions such as If, ThisItem, Patch,
LookUp, and others.
Logic spread out across multiple event handlers (OnSelect,
OnVisible, OnChange, etc.), making the app’s flow hard to follow and
maintain.
Unnecessary calls to data sources, usually because of missing caching
or centralized data loading.

These patterns reveal code duplication and key design flaws, including
poor reuse of components and context variables, unclear separation
between logic and UI, overuse of UI controls for logic, and limited use of
custom functions to simplify repetitive tasks.

Power Apps Canvas apps are sensitive to the number of controls on a


screen. Using hidden controls to manage logic can negatively affect
performance by increasing rendering time and app complexity.
Additionally, using hidden controls like Timer or invisible buttons purely
to trigger logic degrades user experience and makes debugging far more
cumbersome.

It is essential to adopt a modular and centralized approach to Power Fx


development to avoid scenarios where identical logic is replicated across
multiple screens (e.g., a button executing an expression on one screen
and another button doing the same on a different screen).

It is also important to centralize business logic within shared functions or


structures for effective data and state management.

Therefore, let’s begin by exploring the strategies and practices that help
us prevent waste and improve our applications!
Named Formulas
Named formulas are an important first step toward a more structured
and modular approach in Power Apps Canvas development.

They allow developers to assign a name to a Power Fx expression,


making it globally reusable across the app.

Key benefits include:


Immutability, ensuring predictable behavior
Reusability, by referencing the same logic throughout the app
Improved maintainability, by reducing reliance on global variables
initialized in OnStart.

Source : https://www.microsoft.com/en-us/power-platform/blog/power-apps/power-fx-introducing-named-formulas/

While this approach fosters cleaner and more modular code, it still has
notable limitations. Ideally, we should be able to define true functions
that accept parameters, include type definitions, and support structured
logic.
Such capabilities would enable the creation of more advanced and
maintainable architectures, better aligned with software development.

Let’s explore User Defined Functions.


User Defined Function
User Defined Functions (UDFs) are reusable blocks of logic that can be
defined within Canvas apps to centralise complex formulas and improve
code readability.
They allow you to define logic once and reuse it throughout the app,
simplifying maintenance through centralised updates and promoting
cleaner, more organised code even within custom components.

function name arguments

return type

function body

To activate this functionality, navigate to Settings > Updates > Preview


and toggle the corresponding option.
Below are some examples of User-Defined Functions, simple but useful
for illustrating the syntax and demonstrating the use of different data
types.

Using the formula simply requires referencing it within the desired


control. In this case, the fxHelloWorld function has been used in a Text
control, displaying the value returned by the function as its output.

In the following sections of this guide, we will examine the reasons why I
believe that adopting the 'fx' prefix for UDFs may be less than ideal.

From the previous examples, we’ve seen the use of standard types. But
what if we need greater flexibility and want to define custom types?

Let’s introduce User Defined Type.


User Defined Type
User Defined Types (UDT) enable tables and records to be passed in and
out of UDFs.

Source : https://www.microsoft.com/en-us/power-platform/blog/power-apps/power-fx-introducing-named-formulas/

In this case is defined a new type called PaperType is defined with three
properties: Name, Width, and Height, each explicitly specifying its type.

The custom data type feature, although still experimental, opens the
door to a broad range of solution design possibilities.

It allows developers to create strongly typed data structures, improving


consistency.

A common scenario is representing data from a logical join of collections.


Defining a custom data type formalizes the schema, making integration
cleaner, logic more maintainable, and better data manipulation.

To activate this functionality, navigate to Settings > Updates >


Experimental and toggle the corresponding option.
Below is a concise example of a User-Defined Type (UDT).
OrderDetailType is defined with four properties, including one of type
ProductType. Additionally, a new type is declared as an array of
OrderDetailType.

The fxGetOrderList function returns an object of type OrderDetailsList.


In this simple example, the With block is used to create two
OrderDetailType objects, which represent the function’s return value.
This function can be used directly in a gallery’s Items property.
UDTs becomes especially powerful when used in conjunction with the
Parse JSON action.
Parse JSON allows you to deserialize a raw JSON string into an object that
can be used within your flow.

However, by default, it returns an untyped object, which means you


must manually reference property names without type safety or
IntelliSense support.

By defining a custom data type that matches the structure of the


expected JSON object, you unlock the ability to bind directly to its
properties.

Let’s see this in practice with an example.

I have prepared a simple Power Automate flow that uses the HTTP action
to consume a public REST API provided by fakestoreapi.com. The HTTP
action calls the endpoint /products/{id} to retrieve information about a
specific product, then returns the response as text to Power Apps.
Then, in Power Apps under the formulas, I define the data model
corresponding to the response received from the REST API.

Note: The defined custom type must


exactly match the structure of the JSON
response. Partial definitions or omitting
properties are not supported. Every
expected field must be present in the type
definition. Otherwise, the parsing will fail.

Using the button below, called 'Flow Button', we retrieve the response
data from the cloud flow. Inside its OnSelect property, I save the
response and then use ParseJSON, passing the appropriate type as an
argument.

As a result, fakeStoreProductJson contains the typed response, allowing


us to easily leverage IntelliSense to select the required properties. This
approach significantly simplifies the use of ParseJSON.
Components & Enanched componet
properties

Components allow developers to create custom, reusable controls that


can be used across multiple screens or even different applications.

This not only improves consistency in UI design but also enhances


maintainability and scalability, as updates can be applied universally
rather than modifying individual instances.

You can create a component directly


within an app from Tree view.

In Power Apps, you can use a


Component Library to manage and
reuse components across multiple
apps.

Component Libraries are the recommended approach for organizing and


storing multiple components in a centralized location. They allow
developers to maintain consistency across different applications by
enabling easy reuse, updates, and version control of shared components.

This not only enhances development efficiency but also ensures a more
structured and scalable app architecture, reducing redundancy and
maintenance efforts.
We can think of components as the building blocks for constructing a
page.

To make components dynamic and interactive, we use properties (props),


which act like parameters allowing components to receive and send data.

Component Properties are an essential part of creating interactive and


reusable components. Makers can use four types of properties in
components enabling Enanchecd Component Properties:

1️⃣ Data: can send or receive values


🔹 Input (app provides data to the component)
🔹 Output (component provides data to the app)
2️⃣ Function: define logic-based operations, like calculations or text
modifications.
🔹 Input (app provides a function that the component can call)
🔹 Output (component provides a function the app can call)
3️⃣ Action: similar to Output Functions but can modify
variables/collections.
🔹 Example: A Clear() action that resets values inside the component.
4️⃣ Event: it can fire an event and trigger app-defined logic.
🔹 Example: OnSelect or OnChange events.
For this guide, we will only need the event property.

Important: This guide does not cover the details of creating events from
components or enhanced component properties in general. I have already
prepared a dedicated guide that explains their behavior. If you haven’t seen it
yet, I recommend checking it out here. In the following pages, it will be
assumed that the concepts and benefits are already understood.

The image below show how communication flows between a component


and the app. For example, a game list component renders each game
with a discount button. When clicked, it triggers an event that calls a
function defined in the main app. The component’s role is solely to
display information received as input

We are therefore centralizing all the logic related to the call at the
main app level, removing dependencies on a potential datasource,
such as a custom connector, which may be subject to changes.
State Management
It’s time to encapsulate everything we’ve covered so far and explore ways
to improve our Power Apps Canvas applications
Application state management enables efficient control and
synchronization of data, user interface, and behavior across different
components. This approach improves app scalability, reduces
development complexity, and prevents potential state inconsistencies,
ensuring a smoother and more reliable user experience.
Let’s try to figure out its behavior using this diagram

Let’s take a closer look at the individual components involved in building


a state management pattern within Power Apps.
We start with the main application, which consists of multiple
components.
When a user performs an action, such as creating, updating, or deleting a
record, an event is triggered, known as a dispatch. The app processes
this event and determines the type of action to handle.
Next in the flow is the reducer, a pure function responsible for updating
the application state based on the dispatched action.

The reducer modifies the collection, resulting in a new consistent state.


The outcome is a global store that is automatically updated and
synchronised across all screens and components that rely on it.

This approach not only prevents the duplication of collections but also
improves maintainability and ensures data remains centralized and
consistent throughout the app.

In the context of Power Apps, where the concept of reducers doesn't


exist in the same explicit way as in React or Redux, simplifying the
architecture is often the most effective approach for explaining complex
topics like state management.

Instead of implementing a full reducer pattern with a switch-case over


action types, I opted for a simplified approach that feels more natural in
Power Apps. The idea is similar to having a dedicated useCart service,
where state and logic are encapsulated and react to events as if within a
useEffect hook.

This allows for clearer organisation and separation of concerns without


introducing unnecessary complexity.

Let’s see all in action with a Demo!


Demo
In this example, we will put into practice the concepts discussed earlier
by simulating the behavior of an e-commerce platform. On the
homepage of AppCommerce, a component dedicated to managing and
dynamically displaying products will be used.

Component

Main App
The component includes an input property of type table to receive the list
of products to be rendered, as well as an event property that we will
explore shortly. Additionally, under formulas, I defined the data models
representing both the product item and the cart item.
Now we need to define our service to allows you to centralize cart state,
avoid duplication, and easily reuse logic across multiple components
without introducing the added complexity of a full reducer.

Within the useCart domain, I defined the core functions responsible for
managing the cart state: addToCart, removeFromCart, clearCart,
increaseQuantity, and decreaseQuantity.

addToCart handles the addition of a ProductType item to the CartStore.


If the item already exists in the store, it updates only the quantity by
calling the increaseQuantity function instead of duplicating the entry.

Note that instead of using the 'fx' prefix, I use the service name followed
by the action. This makes it easy to immediately recognize the function
and distinguish it from those of other services.
The functions removeFromCart and clearCart are responsible for
managing item removal from the CartStore: removeFromCart deletes a
specific item, while clearCart resets the entire store

increaseQuantity allows you to increment the quantity of a specific


product, which is passed as an argument to the function.
decreaseQuantity decreases the quantity of a specific product and
removes it from the store if the quantity falls below 1.

In the component, I created a custom property Event called


invokeAddToCartEvent, which is triggered when the 'Add to Cart' button
is clicked. Then, in the main app, I specify the logic for this custom
property. in this case, calling useCart_addToCart with the selected
product passed as an argument to the function.
By selecting ‘Add to Cart,’ the cart is updated accordingly. Using the ‘Go to
Cart’ button, we can then navigate to the cart screen.

It’s important to note that in the example below, we’re on a different


screen specifically dedicated to cart management. However, we’re still
working with the global state. No new functions or expressions are
defined to interact with the store. We simply reuse the centralized
functions provided by the useCart service, such as clearCart,
increaseQuantity, and decreaseQuantity
Conclusion

The approach outlined in this guide has proven to offer tangible benefits
in terms of maintainability and consistency within the application. By
centralising logic within dedicated services such as useCart, we avoid
fragmented or unsustainable patterns, like relying on hidden buttons,
toggles, or duplicated expressions scattered across multiple screens.

One of the key advantages is the reduction of error-prone scenarios. For


example, defining a formula in one screen to update a collection, and
then modifying the same collection using a different logic in another
screen, can easily introduce inconsistencies and unpredictable behaviour.

Centralising both state and actions significantly mitigates these issues,


resulting in more reliable and predictable app behaviour.

That said, it's important to recognise that some of the features


demonstrated are currently in preview or experimental stages. Therefore,
cautious and mindful adoption is strongly recommended.

Nevertheless, starting to explore and understand these features now is a


strategic move. It not only prepares developers to take full advantage of
upcoming capabilities but also contributes to shaping emerging new
solutions as the platform continues to evolve.
IF YOU LIKE THIS POST
AND IT WAS HELPFUL
TO YOU.

1.ADVISES THE POST


2.SHARE IT WITH FRIENDS
3.SAVE IT FOR THE FUTURE

Thanks.

nicoloferranti.net

You might also like