Dynamic Content and Expressions
Complete the full lesson to earn 25 points
Work through each section, then tap “Mark as Complete” on the last one.
✦ Skip the page breaks and see fewer ads — read each lesson on a single page with Pro
Mastering Dynamic Content and Expressions in Cloud Flows
Introduction: The Power of Flexibility in Automation
In the world of cloud-based process automation, static workflows are rarely sufficient. If a flow could only perform the same action on the same data every single time, its utility would be strictly limited to the most basic tasks. To build truly helpful automations, your flows must be able to adapt to the data they receive. This is where dynamic content and expressions come into play. They are the engine that allows your automation to inspect incoming data, transform it, perform calculations, and make logical decisions based on the specific context of each run.
Dynamic content refers to the data generated by previous steps in your flow—such as the subject of an email, the name of a user who submitted a form, or the date a file was created. Expressions, on the other hand, are the logic and functions you apply to that data to manipulate it. Think of dynamic content as the "raw material" and expressions as the "tools" used to process that material into a finished product. Mastering these two concepts is the difference between building a simple notification bot and creating a sophisticated business process engine that can handle complex data transformations.
Understanding these concepts is critical because modern business processes are messy. Data rarely arrives in the exact format you need. You might receive a date in a format that your database doesn't recognize, or you might need to extract a specific string of text from a messy email body. By leveraging dynamic content and expressions, you gain control over your data flow, ensuring that your automations are accurate, reliable, and capable of handling real-world complexity.
Understanding Dynamic Content
Dynamic content is the lifeblood of a cloud flow. Every action you add to your flow typically produces an output—data that is available for subsequent steps. When you click into a field in a later step, the flow designer displays a list of available dynamic content from the preceding actions. This list changes based on what you have built previously, providing a contextual map of the data moving through your system.
How Dynamic Content Works
When you select an item from the dynamic content picker, the flow designer inserts a token into the field. This token acts as a placeholder. When the flow runs, the engine replaces that token with the actual value retrieved from the previous step. For example, if you are building a flow that sends an email when a new item is added to a SharePoint list, the "Title" of the list item becomes dynamic content that you can insert into the "Subject" line of your email.
Data Types and Limitations
It is important to remember that dynamic content carries a data type. Some tokens are strings (text), others are integers (whole numbers), floats (decimals), booleans (true/false), or complex arrays (lists of data). While the flow designer often handles these types automatically, you will occasionally encounter scenarios where you need to explicitly convert one type to another. For instance, if you receive a number as a string from an HTTP request and you need to perform a mathematical calculation on it, you cannot simply add it to a number; you must first convert it to an integer using an expression.
Callout: Dynamic Content vs. Expressions Dynamic content represents the raw values passed from one action to another, acting as variables that hold specific information. Expressions, conversely, are the functional logic applied to those values. While dynamic content is what you see in the UI as selectable tokens, expressions are the programmatic instructions you write to transform, format, or evaluate that content. You use dynamic content as the input for your expressions.
Harnessing the Power of Expressions
Expressions allow you to go beyond simply passing data from point A to point B. They allow you to perform data manipulation, string formatting, mathematical operations, and conditional logic directly within the action fields. Expressions are written in a specialized syntax that resembles Excel formulas or programming functions.
The Expression Editor
To write an expression, you click on the "Expression" tab within the dynamic content picker. This opens a text box where you can type your logic. The syntax follows a standard pattern: functionName(argument1, argument2). You can nest functions inside one another to perform multiple operations in a single step, which is a powerful way to keep your flows clean and efficient.
Common Categories of Expressions
The library of available functions is extensive, but most developers find themselves using a specific subset of these functions for the majority of their work. We can categorize them as follows:
- String Functions: Used to manipulate text. Examples include
concat(),substring(),replace(), andtrim(). - Collection Functions: Used to work with arrays of data. Examples include
first(),last(),length(), andcontains(). - Date and Time Functions: Used to calculate or format dates. Examples include
utcNow(),addDays(), andformatDateTime(). - Math Functions: Used for calculations. Examples include
add(),sub(),mul(), anddiv(). - Logical Functions: Used to create conditions. Examples include
if(),and(),or(), andequals().
Practical Examples of Expressions
Let’s look at a few scenarios where expressions save time and reduce the need for extra actions in your flow.
1. Concatenating Strings
Suppose you are creating a contact record and you have "First Name" and "Last Name" as separate pieces of dynamic content. You want to save them as a "Full Name" field. Instead of adding a separate "Compose" action, you can use the concat() function directly in your update action:
concat(triggerBody()?['FirstName'], ' ', triggerBody()?['LastName'])
2. Formatting Dates
Dates often arrive in ISO 8601 format (e.g., 2023-10-27T10:00:00Z). If you need this date for a human-readable email, you can use the formatDateTime() function:
formatDateTime(triggerBody()?['CreatedDate'], 'MMMM dd, yyyy')
3. Handling Null Values
One of the most common pitfalls in automation is a flow failing because a field is empty. You can use the coalesce() function to provide a fallback value:
coalesce(triggerBody()?['PhoneNumber'], 'No phone number provided')
Note: When using expressions, always ensure you have the correct syntax. A missing parenthesis or a typo in a function name will cause the flow to fail at runtime. Always test your expressions in a development environment before deploying to production.
Step-by-Step: Extracting and Transforming Data
Let’s walk through a practical scenario: You receive an email with a subject line like "Request: Project Alpha - [Urgent]". You want to extract the project name ("Project Alpha") and ignore the rest.
- Trigger: Use the "When a new email arrives" trigger.
- Action: Add a "Compose" action.
- Expression: Click the "Expression" tab.
- Logic: We need to find the text between "Request: " and " -". We can use
substring()andindexOf()functions.- First, find the starting position of the project name:
add(indexOf(triggerOutputs()?['body/subject'], 'Request: '), 9) - Find the length of the string to extract:
sub(indexOf(triggerOutputs()?['body/subject'], ' -'), ...)
- First, find the starting position of the project name:
- Implementation: Combine these into a single expression. While this can be complex, it is much faster than running multiple string-parsing actions.
By using these functions, you avoid creating "clutter" in your flow. A clean flow is easier to debug and maintain. If you find yourself adding more than three "Compose" or "Set Variable" actions to format a single piece of data, consider whether an expression could handle the transformation in one step.
Best Practices for Dynamic Content and Expressions
1. Keep Expressions Readable
While it is possible to write incredibly long, nested expressions, doing so makes them difficult to read and troubleshoot. If your expression is more than three levels deep, consider breaking it into multiple "Compose" actions. This allows you to inspect the output of each stage of the transformation, making it much easier to identify where an error might be occurring.
2. Always Use the Expression Editor
Never try to type expressions directly into the standard dynamic content fields without the editor. The editor provides syntax highlighting and validation, which significantly reduces the risk of typos. If you try to type an expression manually, you will often miss the leading @ symbol or misplace a closing parenthesis, which will cause the expression to be treated as a literal string rather than executable code.
3. Handle Empty Outputs (The "Safe" Approach)
Always assume that dynamic content might be empty or null. If you try to perform a function on a null value, the flow will fail. Use the if() function or the coalesce() function to check for null values before attempting to process data.
- Example:
if(equals(triggerBody()?['Status'], null), 'Pending', triggerBody()?['Status'])
4. Leverage "Compose" for Debugging
When building complex logic, use "Compose" actions as "watch windows." Before you use a complex expression in your final action (like an email or database update), put the expression inside a "Compose" action. Run the flow, look at the output of the "Compose" action, and verify that the result is exactly what you expected. Once confirmed, you can copy and paste that expression into your final action.
5. Document Your Logic
If you are using a complex expression, add a note to the action describing what the expression is doing. This is particularly important in team environments where other colleagues may need to maintain your flows. A simple comment like "Extracts project name from email subject" can save hours of confusion for someone else tasked with updating the flow later.
Common Pitfalls and How to Avoid Them
Pitfall 1: The "Expression as Text" Error
This occurs when you type an expression into a field without using the Expression Editor. The engine treats your code as a literal string.
- How to avoid: Always click the "Expression" tab in the dynamic content picker. If the field doesn't show an "Expression" tab, it means the field does not support expressions.
Pitfall 2: Incorrect Data Type Conversions
Attempting to perform math on a string or concatenating a number to a string without conversion will cause errors.
- How to avoid: Use functions like
int(),float(), orstring()to explicitly convert data types before performing operations. For example,add(int(variables('count')), 1)ensures that the addition happens mathematically.
Pitfall 3: The "Array Index Out of Bounds" Error
When working with arrays (like a list of items returned from a database), trying to access the first item when the array is empty will cause a failure.
- How to avoid: Always check the length of the array first using the
length()function, or use thefirst()function carefully after verifying that the array is not empty.
Pitfall 4: Time Zone Confusion
The utcNow() function returns the time in UTC. If your business process relies on local time, you might find that your dates are off by several hours.
- How to avoid: Use the
convertFromUtc()function to shift the time to your specific time zone.convertFromUtc(utcNow(), 'Pacific Standard Time', 'yyyy-MM-dd')
Comparison Table: Common Expression Functions
| Category | Function | Purpose | Example |
|---|---|---|---|
| String | concat() |
Joins two or more strings | concat('Hello', ' ', 'World') |
| String | substring() |
Extracts a portion of a string | substring('Hello', 0, 2) -> 'He' |
| Math | add() |
Adds two numbers | add(10, 5) -> 15 |
| Logic | equals() |
Checks if two values are equal | equals(triggerBody()?['ID'], 1) |
| Date | utcNow() |
Gets the current timestamp | utcNow() |
| Collection | length() |
Returns the number of items | length(outputs('Get_items')?['body/value']) |
| Conversion | int() |
Converts value to integer | int('123') -> 123 |
Advanced Logic: Working with Conditions and Loops
While dynamic content and expressions are powerful, they are often paired with "Control" actions like "Condition" (if/else) and "Apply to Each" (loops).
Using Expressions in Conditions
You don't always need an "Expression" box to use logic. In a "Condition" action, you can select dynamic content and then choose an operator (e.g., "is equal to," "contains," "starts with"). However, if you need to compare two calculated values, you can switch to the "Advanced Mode" (or simply use the Expression tab) to write complex logic:
and(greater(triggerBody()?['Amount'], 100), equals(triggerBody()?['Status'], 'Approved'))
Expressions inside Loops
When you use an "Apply to Each" loop, you are iterating over an array. Inside the loop, you can use expressions to reference the "Current Item." This is often done using the items() function.
- Example:
items('Apply_to_each')?['EmailAddress']This retrieves the email address from the specific item currently being processed in the loop. Understanding theitems()function is essential for any flow that processes batches of data, such as syncing files or updating multiple database records.
Warning: Be careful with nesting loops. If you have an "Apply to Each" inside another "Apply to Each," you must be very specific with your expressions to reference the correct loop's items. Using the same variable names or confusing the scope of the
items()function is a common source of bugs in complex flows.
Troubleshooting and Debugging Strategies
When a flow fails, the first step is to open the specific "Run" history of that flow. Click on the action that failed to see the "Inputs" and "Outputs." If an expression failed, the output will often show an error message.
- Check the Raw Inputs: Look at the "Raw Inputs" JSON. Does the data look the way you expected? Often, the issue is that the source system sent a null or unexpected format.
- Verify the Expression Output: If you used a "Compose" action for your expression, check the "Outputs" of that specific action. If the "Compose" action succeeded but the following action failed, the error is likely in how the data was passed to the next step.
- Use "Test" Mode: The flow designer has a "Test" feature that allows you to manually trigger a flow. Use this to iterate quickly. Change your expression, run the test, and see if the result improves.
- Simplify: If you cannot figure out why an expression is failing, strip it down to the bare minimum. Start with a single function, verify it works, and then add the next layer of complexity.
Industry Best Practices for Scalable Flows
As your library of cloud flows grows, maintaining them becomes a challenge. Adopting a few industry-standard habits will make your life much easier in the long run.
- Standardize Naming: Give your "Compose" actions meaningful names. Instead of "Compose," use "Compose - Format Date" or "Compose - Extract Project ID." This makes the flow map readable at a glance.
- Environment Strategy: Always develop in a non-production environment. Never test your expressions on live, production data. Once you have validated your logic, you can move the flow to production.
- Error Handling: Use the "Configure Run After" setting on actions to handle failures gracefully. For example, you can have a "Send an Email to Admin" action that only runs if a previous, critical action fails. You can use expressions within that email to include the error message:
outputs('Action_Name')?['error']?['message']. - Avoid Over-Engineering: If a requirement can be met with a simple "Condition" action instead of a complex, nested expression, use the "Condition" action. It is easier for other people to understand and easier to debug.
Frequently Asked Questions (FAQ)
Q: Can I use variables to store the result of an expression? A: Yes. You can use a "Set Variable" action and put your expression into the "Value" field. This is a great way to store a calculated value to be used multiple times throughout the flow.
Q: What happens if I use an expression on a field that doesn't support it? A: The flow designer will generally prevent you from entering an expression if the field does not support it. If you force it through an import or API, the flow will fail at runtime.
Q: Are expressions case-sensitive?
A: Generally, function names are case-insensitive, but string comparisons within functions are case-sensitive. equals('Apple', 'apple') will return false.
Q: Can I use custom JavaScript? A: Cloud flows are designed to be low-code. While you cannot write raw JavaScript directly in the flow, you can use "Azure Functions" or "HTTP" actions to call external code if your logic is too complex for standard expressions.
Key Takeaways
- Dynamic Content is Contextual: It is the data provided by previous steps, acting as the foundation for all your automation logic.
- Expressions are Transformative: They allow you to manipulate, format, calculate, and evaluate that dynamic content, turning raw data into actionable information.
- Readability Matters: Prioritize clear, simple expressions over complex, deeply nested ones. Use "Compose" actions to break down logic and aid in debugging.
- Handle Nulls Proactively: Always assume data might be missing. Use functions like
coalesce()orif()to provide fallback values and prevent flow failures. - Test in Isolation: Use the "Test" feature and "Compose" actions to isolate and verify your logic before implementing it in critical, final steps.
- Consistency is Key: Use naming conventions for your actions and document your complex expressions. This ensures your flows remain maintainable as they grow in complexity and number.
- Leverage the Tooling: Always use the Expression Editor rather than typing manually to ensure correct syntax and benefit from built-in validation.
By mastering these elements, you move from being a user of automation to an architect of business processes. The ability to dynamically handle data is the hallmark of a professional-grade automation developer. As you practice these techniques, you will find that the limitations of your automation tools diminish, allowing you to build increasingly sophisticated solutions that solve real-world problems with precision and reliability.
Enjoying the courses?
Everything stays free. Pro shows fewer ads, doubles your daily points limit so you progress twice as fast, and lets you read each lesson on one page.
- ✓ Fewer advertisements
- ✓ 2× daily points limit
- ✓ Distraction-free lessons