Modern Commanding with Power Fx

Earn 25 points (50 with Pro) in two steps

  1. ① Read through the lesson — each section gets a ✓ as you scroll through it.
  2. ② When every section has a ✓, tap Complete lesson.

0 of 11 read · keep scrolling

✦ See fewer ads and earn double points — 50 a lesson instead of 25 — with Pro

Modern Commanding with Power Fx in Model-Driven Apps

Welcome to this comprehensive lesson on Modern Commanding with Power Fx in Microsoft Power Apps Model-Driven Apps. This topic represents a significant evolution in how we customize user experiences within our business applications, moving away from complex, code-heavy methods to a more accessible, low-code approach.

Traditionally, customizing command bars in Model-Driven Apps involved a significant learning curve, often requiring deep knowledge of XML, JavaScript, and specialized tools like the Ribbon Workbench. While powerful, this approach could be cumbersome, difficult to maintain, and a barrier for citizen developers. Modern Commanding with Power Fx changes this paradigm entirely, bringing the familiar, Excel-like Power Fx language directly into the command bar customization experience. This shift empowers a broader range of developers, from professional coders to business analysts, to create dynamic and intelligent command buttons that respond to context and drive specific actions.

This lesson will guide you through understanding what Modern Commanding is, why it's a game-changer, and how to implement it effectively using Power Fx. We'll explore practical examples, delve into the nuances of Power Fx for various command properties, discuss best practices, and help you navigate common pitfalls. By the end of this lesson, you'll be equipped to design and deploy sophisticated command bar experiences that enhance user productivity and streamline business processes in your Model-Driven Apps.

Not read yet

Understanding Modern Commanding

In Model-Driven Apps, command bars are the rows of buttons that appear at the top of forms, views, and grids. These buttons allow users to perform actions like saving a record, deleting an item, or triggering a business process. Before modern commanding, customizing these buttons was a task often reserved for experienced developers.

The traditional method for customizing commands involved:

  • Ribbon Definition XML: Modifying the underlying XML structure that defines the command bar buttons. This was complex and prone to errors.
  • JavaScript Web Resources: Attaching JavaScript functions to command buttons to define their actions and visibility rules. This required coding skills and careful management of web resources.
  • Ribbon Workbench: A community tool that provided a graphical interface to simplify the editing of Ribbon Definition XML, but still required understanding the underlying concepts and sometimes JavaScript.

Modern Commanding, introduced by Microsoft, streamlines this entire process by replacing XML and JavaScript with Power Fx. Power Fx is the low-code language used across the Power Platform, most notably in Canvas Apps. By bringing Power Fx to Model-Driven App commands, Microsoft aims to unify the development experience, making it easier to build and maintain applications across the platform.

What is a Command Bar?

Before diving into Power Fx, let's quickly review where command bars appear in Model-Driven Apps:

  • Main Form: Buttons at the top of a record's form (e.g., Save, Activate, Custom buttons).
  • Grid View (Homepage Grid): Buttons above a list of records in a view (e.g., New, Delete, Export to Excel, Custom buttons).
  • Subgrid: Buttons above a subgrid section within a form (e.g., Add New, See All Records, Custom buttons related to the subgrid's records).
  • Associated View: Buttons when viewing related records in a separate tab (similar to grid view).

Each of these locations can have different command definitions and can be customized independently. Modern commanding allows you to define the behavior and visibility of buttons for each of these contexts using Power Fx.

Callout: The Power Fx Advantage The adoption of Power Fx for Model-Driven App commanding brings several significant advantages. It provides a consistent, declarative language across the Power Platform, reducing the learning curve for developers familiar with Canvas Apps. It also simplifies debugging and maintenance, as the logic is directly associated with the command button properties rather than scattered across multiple JavaScript files. This shift fundamentally democratizes command bar customization, making it accessible to a much wider audience.

Not read yet

Setting Up Your Development Environment

To start creating modern commands, you'll need a Power Apps environment and a solution. Working within a solution is crucial for application lifecycle management (ALM) and ensures your customizations are portable.

Prerequisites:

  1. Power Apps Environment: An environment where you have system customizer or system administrator privileges.
  2. Solution: Create a new solution or use an existing unmanaged solution for your customizations. This is where you'll add the tables and components you want to modify.

Accessing the Modern Command Designer:

  1. Navigate to Power Apps Portal: Go to make.powerapps.com.
  2. Select Your Environment: Ensure you're in the correct environment using the environment picker in the top right corner.
  3. Open Solutions: In the left navigation pane, select "Solutions".
  4. Create/Open Solution: Open an existing solution or create a new one. For this lesson, let's assume you've created a solution named "MyModernCommandsSolution".
  5. Add Table to Solution:
    • Click + New -> Table or + Add existing -> Table.
    • Select the table you want to customize commands for (e.g., "Account").
    • Click "Add".
  6. Open the Command Designer:
    • Once the table is in your solution, select it.
    • In the top menu bar, click "..." (More commands) and then "Edit command bar".
    • A dialog will appear asking you to select the command bar location:
      • Main form
      • Main grid
      • Subgrid view
      • Associated view
    • Choose the desired location (e.g., "Main form") and click "Edit".

This will open the Modern Command Designer, a visual interface where you can add, configure, and publish your custom command buttons.

Not read yet

Creating Your First Modern Command (Step-by-Step Example)

Let's walk through a practical example: adding a custom button to the Account main form that updates a specific field on the Account record.

Scenario: We want a button on the Account form called "Mark as Reviewed". When clicked, it should set a custom field new_lastrevieweddate to the current date and time. The button should only be visible if the account's statuscode is 'Active'.

Step 1: Prepare Your Environment and Solution

  • Ensure you are in make.powerapps.com.
  • Create a new solution named MyModernCommandsSolution.
  • Add the Account table to this solution.
  • Custom Field: Make sure your Account table has a custom DateTime field, for example, new_lastrevieweddate. If not, create one.

Step 2: Open the Command Designer for the Account Form

  1. In MyModernCommandsSolution, select the Account table.
  2. Click "..." (More commands) -> "Edit command bar".
  3. Choose "Main form" and click "Edit".

The Command Designer will load, showing the existing buttons on the Account form's command bar.

Step 3: Add a New Command Button

  1. In the Command Designer, you'll see a + New command button. Click it.
  2. A new button will appear on the command bar preview.

Step 4: Configure Button Properties

On the right-hand pane, you'll see the properties for your new command.

  1. Label: Enter Mark as Reviewed.
  2. Icon: Select an appropriate icon (e.g., search for "check" or "calendar").
  3. Action: Choose Run Power Fx. This is where we'll define what happens when the button is clicked.
  4. Visibility: Choose Show on condition from formula. This is where we'll define when the button appears.

Step 5: Write Power Fx for OnSelect (Action)

Now, let's define what happens when the "Mark as Reviewed" button is clicked. We want to update the current Account record's new_lastrevieweddate field.

  1. In the Command pane on the right, under Action, make sure Run Power Fx is selected.

  2. In the formula bar (labeled OnSelect), enter the following Power Fx:

    Patch(
        Self.Selected.Item,
        { new_lastrevieweddate: Now() }
    );
    Notify("Account marked as reviewed!", NotificationType.Success);
    

    Explanation:

    • Patch(): This function is used to modify or create records.
    • Self.Selected.Item: This refers to the currently selected record on the form. In the context of a form command, it's the record displayed in the current form.
    • { new_lastrevieweddate: Now() }: This is the update payload. It sets the new_lastrevieweddate field to the current date and time using the Now() function.
    • ;: This is used to chain multiple Power Fx statements.
    • Notify(): This function displays a temporary notification message to the user. NotificationType.Success shows a green success message.

Step 6: Write Power Fx for Visible (Visibility Condition)

Next, we'll make the button visible only if the Account's status is 'Active'. For the Account table, the 'Active' status usually corresponds to a statuscode of 1.

  1. In the Command pane, under Visibility, select Show on condition from formula.

  2. In the formula bar (labeled Visible), enter the following Power Fx:

    Self.Selected.Item.statuscode = 1
    

    Explanation:

    • Self.Selected.Item.statuscode: This accesses the statuscode field of the current record.
    • = 1: This checks if the statuscode is equal to 1 (which typically represents 'Active' for the Account entity). If this condition evaluates to true, the button will be visible; otherwise, it will be hidden.

    Tip: To find the integer value for a specific status code or option set value, you can inspect the field's properties in the table designer or use the Monitor tool when testing your app.

Step 7: Save and Publish

  1. In the top right corner of the Command Designer, click Save.
  2. Once saved, click Publish.

Publishing is a two-step process: first, you publish the command definition, and then you publish the Model-Driven App itself to reflect these changes.

Step 8: Test the Command

  1. Navigate to your Model-Driven App.
  2. Open an Account record.
  3. Test Visibility:
    • If the account's status is 'Active', you should see the "Mark as Reviewed" button.
    • If the account's status is 'Inactive' or another status, the button should be hidden. You might need to change the status of an account to test both scenarios.
  4. Test Action:
    • With an 'Active' account, click the "Mark as Reviewed" button.
    • You should see a success notification.
    • Refresh the form or check the new_lastrevieweddate field to confirm it has been updated with the current date and time.

This completes your first modern command using Power Fx! You've successfully defined both the action and the visibility of a custom button.

Not read yet

Deep Dive into Power Fx for Commanding

Now that you've created a basic command, let's explore the Power Fx functions and concepts that are most relevant for customizing command buttons.

OnSelect Property: Defining Actions

The OnSelect property determines what happens when a user clicks the command button. This is where you'll use Power Fx to define the logic for your business processes.

  • Patch() for Updating Records:

    // Update the current record
    Patch(Self.Selected.Item, { name: "Updated Account Name" });
    
    // Update a different record (e.g., related contact)
    Patch(
        LookUp(Contacts, 'Company Name'.Account = Self.Selected.Item),
        { 'Job Title': "Key Contact" }
    );
    

    Patch() is fundamental for data manipulation. It can update existing records or create new ones.

  • Navigate() for Opening Forms/Views:

    // Open a new Account form
    Navigate(Accounts, NewForm);
    
    // Open an existing Contact record (assuming a lookup field)
    Navigate(Self.Selected.Item.'Primary Contact (Contacts)');
    
    // Open a specific view (e.g., "Active Accounts")
    Navigate(Accounts, Table(Name: "Active Accounts"));
    

    Navigate() allows you to transition the user to different forms, views, or even custom pages within your Model-Driven App.

  • Launch() for External URLs:

    // Open an external website
    Launch("https://www.microsoft.com");
    
    // Open a specific record in another app (if you have the URL structure)
    Launch("https://yourorg.crm.dynamics.com/main.aspx?etn=account&pagetype=entityrecord&id=" & Self.Selected.Item.Account);
    

    Launch() is useful for integrating with external systems or opening specific pages outside the current app.

  • Confirm() for User Confirmation:

    If(
        Confirm("Are you sure you want to proceed with this action?", {Title: "Confirm Action"}),
        // User clicked OK
        Notify("Action confirmed!", NotificationType.Success),
        // User clicked Cancel
        Notify("Action cancelled.", NotificationType.Error)
    );
    

    Confirm() presents a dialog to the user, prompting them to confirm an action before proceeding. It returns true if "OK" is clicked, false if "Cancel".

  • Notify() for Displaying Messages:

    Notify("Operation completed successfully!", NotificationType.Success);
    Notify("Warning: Some data might be missing.", NotificationType.Warning);
    Notify("Error: Failed to save record.", NotificationType.Error);
    

    Notify() provides immediate feedback to the user, which is crucial for a good user experience. You can specify different notification types (Success, Warning, Error, Info).

  • Set() for Local Variables:

    Set(varMyVariable, "Hello World");
    Notify(varMyVariable);
    

    Set() creates a local variable within the scope of the command's OnSelect formula. These variables are temporary and are reset when the command finishes execution. They are useful for breaking down complex logic or storing intermediate values.

  • Chaining Commands with ;: As seen in the example, you can execute multiple Power Fx statements sequentially by separating them with a semicolon. The statements will run in order.

Visible Property: Controlling Visibility

The Visible property determines whether the command button is displayed at all. It expects a boolean (true/false) result.

  • Conditional Visibility based on Field Values:

    // Visible if the 'statuscode' field of the current record is 'Active' (value 1)
    Self.Selected.Item.statuscode = 1
    
    // Visible if a custom checkbox field is true
    Self.Selected.Item.new_isapproved = true
    
    // Visible if a text field is not empty
    !IsBlank(Self.Selected.Item.description)
    

    This is the most common use case, dynamically showing or hiding buttons based on the data of the current record.

  • Combining Conditions:

    // Visible if status is Active AND a specific field is not blank
    Self.Selected.Item.statuscode = 1 And !IsBlank(Self.Selected.Item.new_requiredfield)
    
    // Visible if status is Active OR status is On Hold
    Self.Selected.Item.statuscode = 1 Or Self.Selected.Item.statuscode = 2
    

    Use And, Or, Not operators to build complex visibility rules.

  • Visibility for Grid Commands (Multiple Selections): For commands on grids (main grid, subgrid), you often need to check how many items are selected.

    // Visible if at least one item is selected
    CountRows(Self.Selected.AllItems) > 0
    
    // Visible if exactly one item is selected
    CountRows(Self.Selected.AllItems) = 1
    
    // Visible if multiple items are selected
    CountRows(Self.Selected.AllItems) > 1
    

    Self.Selected.AllItems is a table of all currently selected records in the grid. CountRows() returns the number of records in that table.

Enabled Property: Controlling Interactivity

The Enabled property determines whether the command button is clickable (enabled) or grayed out (disabled). It also expects a boolean result.

  • Similar to Visible but for interactivity:
    // Enabled if a required field is populated
    !IsBlank(Self.Selected.Item.new_requiredfield)
    
    // Enabled if the record is not read-only (assuming a field indicates this)
    Self.Selected.Item.new_isreadonly = false
    
    The logic for Enabled is very similar to Visible. The key difference is the user experience: a disabled button is still visible but visually indicates it cannot be clicked, whereas a hidden button is simply not there. Use Enabled when you want to inform the user that an action could be taken, but conditions aren't met yet. Use Visible when the action is completely irrelevant or unauthorized in the current context.

Not read yet

Accessing Contextual Data

A crucial aspect of modern commanding is the ability to access data relevant to the current context.

  • Self.Selected.Item:

    • Context: Used in form commands.
    • Description: Refers to the single record currently displayed in the form. You can access its fields directly, e.g., Self.Selected.Item.name, Self.Selected.Item.statuscode.
  • Self.Selected.AllItems:

    • Context: Used in grid commands (main grid, subgrid, associated view).
    • Description: Refers to a table of all records currently selected in the grid. This is essential for bulk actions.
    • To access individual items or their fields, you'll typically use functions like First(), Last(), Filter(), or ForAll() with this collection.
  • User():

    • Context: Available in all command contexts.
    • Description: Returns a record containing information about the current user.
    • Properties:
      • User().Email: The user's primary email address.
      • User().FullName: The user's full name.
      • User().Id: The user's unique ID (GUID).
      • User().Image: A link to the user's profile image.
    • Example: Notify("Hello, " & User().FullName);
  • Table References: You can directly reference tables in your environment to perform lookups, filters, or aggregations.

    // Check if the current user is a member of a specific team (requires Team membership table)
    // This is a more advanced scenario, often better handled with security roles.
    LookUp(Teams, 'Team Name' = "Sales Team").'Team ID' in User().Teams.'Team ID' // Simplified example
    

    Note: When using LookUp or Filter on large tables or across relationships in Visible or Enabled properties, be mindful of performance. Complex data retrieval in these properties can slow down the UI. Consider simplifying the logic or moving it to the OnSelect property if performance becomes an issue.

Not read yet

Advanced Scenarios and Best Practices

Let's explore some more advanced use cases and crucial best practices for building robust modern commands.

Multiple Record Selection (Grid Commands)

When designing commands for grids, you often need to perform actions on multiple selected records. Self.Selected.AllItems is your key here.

Example: Bulk Update Status for Selected Accounts

Let's say you want a button on the Account main grid to mark all selected accounts as "On Hold".

  1. Open the Command Designer for the Account table, Main grid.

  2. Add a new command:

    • Label: Set On Hold
    • Icon: Choose a suitable icon.
    • Action: Run Power Fx
    • Visibility: Show on condition from formula
  3. OnSelect Power Fx:

    ForAll(
        Self.Selected.AllItems,
        Patch(
            Accounts,
            ThisRecord, // 'ThisRecord' refers to the current item in the ForAll loop
            { statuscode: 2 } // Assuming '2' is the value for 'On Hold' status
        )
    );
    Notify(CountRows(Self.Selected.AllItems) & " accounts set to On Hold.", NotificationType.Success);
    

    Explanation:

    • ForAll(): This function iterates over a table (in this case, Self.Selected.AllItems) and applies a formula to each record.
    • ThisRecord: Inside ForAll, ThisRecord refers to the current record being processed in the loop.
    • Patch(Accounts, ThisRecord, { ... }): This updates the specific record (ThisRecord) within the Accounts table with the new statuscode.
  4. Visible Power Fx:

    CountRows(Self.Selected.AllItems) > 0
    

    This ensures the "Set On Hold" button is only visible if at least one account is selected in the grid.

Working with Related Records

You can use Power Fx to fetch and manipulate related records, though this can become complex quickly.

Example: Button to Create a Related Task for an Account

  1. Open the Command Designer for the Account table, Main form.

  2. Add a new command:

    • Label: Create Follow-up Task
    • Icon: Choose a suitable icon.
    • Action: Run Power Fx
    • Visibility: Show on condition from formula
  3. OnSelect Power Fx:

    Patch(
        Tasks,
        Defaults(Tasks),
        {
            Subject: "Follow up with " & Self.Selected.Item.name,
            'Regarding (Accounts)': Self.Selected.Item, // Link to the current Account
            'Due Date': DateAdd(Now(), 7, Days) // Due in 7 days
        }
    );
    Notify("Follow-up task created for " & Self.Selected.Item.name, NotificationType.Success);
    

    Explanation:

    • Patch(Tasks, Defaults(Tasks), { ... }): This creates a new Task record. Defaults(Tasks) provides default values for the new record.
    • 'Regarding (Accounts)': Self.Selected.Item: This is how you establish a lookup relationship. You set the lookup field (e.g., Regarding (Accounts)) to the entire record object of the Self.Selected.Item (the current Account).
  4. Visible Power Fx:

    Self.Selected.Item.statuscode = 1 // Only if the account is active
    

Calling Power Automate Flows

For complex business logic, integrations, or operations that require server-side processing, calling a Power Automate Cloud Flow from a Power Fx command is a powerful pattern.

  1. Create a Cloud Flow:

    • In make.powerautomate.com, create an Instant cloud flow.
    • Choose the trigger: Power Apps (V2). This trigger allows you to pass inputs from Power Apps.
    • Add an input for the record ID (e.g., text type, named RecordId).
    • Add your business logic (e.g., update multiple related records, send an email, call an external API).
    • (Optional) Add a Respond to a PowerApp or flow action to send data back to Power Apps.
  2. Integrate in Power Fx:

    • In the Command Designer, for your button's OnSelect property, you can call the flow.
    • First, add the flow to your app in the Command Designer (Data -> Add data -> Search for your flow).
    • Then, in OnSelect:
      'MyFlowName'.Run(Self.Selected.Item.Account); // Pass the Account ID
      Notify("Flow triggered successfully!", NotificationType.Information);
      
      If your flow returns data, you can capture it:
      Set(flowResult, 'MyFlowName'.Run(Self.Selected.Item.Account));
      Notify("Flow returned: " & flowResult.MyOutputField);
      

    Callout: Power Fx vs. Power Automate for Business Logic Power Fx is excellent for client-side logic, simple data updates, and UI interactions. Power Automate (Cloud Flows) excels at complex, multi-step business processes, server-side operations, integrations with other services, and long-running tasks. Use Power Fx for immediate, lightweight actions, and delegate heavy lifting or cross-system orchestration to Power Automate. This separation of concerns leads to more maintainable and scalable solutions.

Error Handling and User Feedback

Always consider how your commands will behave if an error occurs and how you'll inform the user.

IfError(
    // Attempt to update the record
    Patch(Self.Selected.Item, { new_status: "Processed" }),
    // If successful (no error), display success notification
    Notify("Record processed successfully!", NotificationType.Success),
    // If an error occurs, display an error notification
    Notify("Error processing record: " & FirstError.Message, NotificationType.Error)
);

IfError() allows you to define alternative actions when an error occurs. FirstError.Message provides details about the error.

Security Considerations

  • Data Security vs. UI Security: Hiding a button via Visible or disabling it via Enabled does not prevent a user from performing that action if they have the underlying security role permissions and know how to bypass the UI. Always enforce security at the data level (e.g., using Dataverse security roles, field-level security, record ownership).
  • Role-Based Visibility: While you can try to write Power Fx to check user roles, this is often complex and better managed by configuring the command for specific security roles within the command designer. When you publish a command, you can choose which security roles it applies to. This is the recommended approach for role-based security of commands.

Performance

  • Efficient Power Fx: Keep your Visible and Enabled formulas as simple as possible. Avoid complex LookUp or Filter operations that could scan large datasets, as these are evaluated frequently as the UI changes.
  • Delegation: Power Fx can delegate some operations to the Dataverse server, improving performance. Be aware of delegation limits for functions like Filter, LookUp, Search, etc.
  • Testing: Always test your commands with realistic data volumes and network conditions.

Solution Management

  • Always use Solutions: Never customize directly in the default solution. Always work within dedicated, unmanaged solutions for development. This ensures proper ALM.
  • Solution Export/Import: When deploying to other environments, export your solution as managed (for production) or unmanaged (for development/test environments).

Testing Strategy

  • Unit Testing: Test each command individually to ensure its OnSelect, Visible, and Enabled logic works as expected.
  • Role-Based Testing: Test as different users with varying security roles to ensure commands appear and function correctly based on permissions.
  • End-to-End Testing: Test the command as part of a complete business process.
  • Edge Cases: Test with empty fields, invalid data, multiple selections (for grid commands), and records in different states.

Not read yet

Common Pitfalls and How to Avoid Them

Even with the simplicity of Power Fx, there are common mistakes developers make.

  1. Forgetting to Publish: After saving changes in the Command Designer, you must click "Publish" for the changes to take effect in your Model-Driven App. Sometimes, you might need to publish the app itself again after publishing commands.
    • Avoid: Develop a habit of saving and publishing immediately after making significant changes.
  2. Incorrect Context (Self.Selected.Item vs. Self.Selected.AllItems):
    • Using Self.Selected.Item in a grid command (where multiple items can be selected) will likely cause errors or unexpected behavior as it expects a single record.
    • Using Self.Selected.AllItems in a form command (where only one record is present) is also incorrect.
    • Avoid: Always be aware of the command bar location (form vs. grid) and use the appropriate context variable.
  3. Complex Logic in Visible or Enabled:
    • Putting heavy LookUp or Filter operations on large tables in Visible or Enabled can make the UI unresponsive, especially on slower connections.
    • Avoid: Keep Visible and Enabled formulas concise. If complex logic is needed, consider:
      • Simplifying the underlying data model.
      • Pre-calculating values and storing them on the record if possible.
      • Using Power Automate for server-side evaluation if absolutely necessary, but this is less common for simple visibility.
  4. Hardcoding Values:
    • Directly embedding environment-specific values (e.g., URLs, specific user IDs) in your Power Fx formulas makes deployment difficult.
    • Avoid: Use environment variables for configurable values. For user or team IDs, rely on User() functions or security role assignments.
  5. Assuming UI Security = Data Security:
    • Just because a button is hidden doesn't mean the underlying action is blocked. A malicious user could still try to trigger the action programmatically.
    • Avoid: Always enforce security at the Dataverse level using security roles, field-level security, and business rules.
  6. Not Refreshing the Model-Driven App: After publishing, sometimes the changes don't immediately appear in the running app. A hard refresh (Ctrl+F5 or clearing browser cache) might be needed.
    • Avoid: Be patient, but also know when to force a refresh.
  7. Overlooking Delegation Warnings: Power Fx provides warnings when certain operations cannot be fully delegated to the Dataverse server, meaning they might process data locally, which can be slow for large datasets.
    • Avoid: Pay attention to delegation warnings in the formula editor and refactor your formulas to be delegable where possible.

Not read yet

Comparison: Modern Commanding vs. Ribbon Workbench (Quick Reference)

Feature Modern Commanding (Power Fx) Ribbon Workbench (Traditional)
Language Power Fx (low-code, declarative) JavaScript (pro-code, imperative), XML
Tooling In-browser Command Designer XrmToolBox (external tool), Visual Studio (for JS)
Skill Set Citizen developers, business analysts, pro-developers Pro-developers, experienced customizers
Complexity Generally simpler, visual, intuitive Higher complexity, steeper learning curve
Maintainability Easier to read, debug, and maintain Can be challenging, especially with complex JS/XML
ALM Solution-aware, integrated with Power Apps ALM Solution-aware, but requires careful management of web resources
Debugging Formula editor warnings, Monitor tool Browser developer tools, console.log
Performance Generally good, depends on Power Fx complexity and delegation Good, depends on JavaScript efficiency and server calls
Future Outlook Microsoft's preferred and actively developed approach Legacy approach, still supported but less focus
Offline Power Fx supports offline capabilities Requires careful handling of JS for offline

Callout: The Future of Commanding Microsoft is clearly investing heavily in modern commanding with Power Fx. While Ribbon Workbench and JavaScript still have their place for existing customizations and very niche scenarios, the future of command bar customization in Model-Driven Apps undoubtedly lies with Power Fx. New features and capabilities will primarily be developed for the modern commanding experience, making it the default and recommended approach for new projects and for migrating older customizations. Embracing Power Fx now will ensure your solutions are forward-compatible and easier to maintain.

Not read yet

Common Questions (FAQ)

Q: My command isn't showing up. What should I check? A:

  1. Publishing: Did you save and publish the command in the Command Designer? Did you publish the Model-Driven App itself?
  2. Visibility Formula: Is your Visible Power Fx formula evaluating to true in the current context? Check for typos or incorrect field values.
  3. Security Roles: Is the command assigned to the correct security roles, and does your test user have one of those roles?
  4. Solution Scope: Is the command added within your solution?
  5. Browser Cache: Try a hard refresh (Ctrl+F5) or clear your browser cache.

Q: My command shows up but doesn't do anything when clicked. A:

  1. OnSelect Formula: Is your OnSelect Power Fx formula correctly written? Check for syntax errors in the formula editor.
  2. Data Access: Does the user have permission to perform the action (e.g., Patch a record)? Check security roles.
  3. Dependencies: If calling a Power Automate flow, is the flow published and running correctly?
  4. Debugging: Use Notify() statements in your OnSelect formula to trace execution and variable values. The Power Apps Monitor tool can also provide detailed insights into formula execution.

Q: Can I use global variables or context variables like in Canvas Apps? A: Set() can be used for local variables within the OnSelect formula. UpdateContext() and UpdateIf() are not directly applicable in the same way as Canvas Apps as the command context is more transient. For persistent data or data shared across screens, you'd typically rely on Dataverse records.

Q: How do I remove an existing command (e.g., an OOB button)? A: In the Command Designer, select the button you want to hide. On the right pane, set its Visibility to Hide. You can also set a Visible formula that always evaluates to false (e.g., false). Remember to save and publish.

Not read yet

Key Takeaways

  1. Shift to Low-Code: Modern Commanding with Power Fx represents a significant move towards low-code customization for Model-Driven Apps, making command bar modifications more accessible to a wider range of developers.
  2. Unified Language: Power Fx provides a consistent, declarative language across the Power Platform, simplifying development and reducing the learning curve for those familiar with Canvas Apps.
  3. Contextual Awareness: Commands can dynamically adapt their visibility and behavior based on the current record (Self.Selected.Item), selected records (Self.Selected.AllItems), and user information (User()).
  4. Powerful Functions: Leverage key Power Fx functions like Patch() for data manipulation, Navigate() for UI transitions, Notify() for user feedback, and ForAll() for bulk actions on grids.
  5. Integration Capabilities: Power Fx commands can seamlessly integrate with Power Automate flows, allowing you to trigger complex business logic or external integrations from a simple button click.
  6. Best Practices for Robustness: Always work within solutions, prioritize security by combining UI visibility with Dataverse security roles, ensure efficient Power Fx for performance, and implement proper error handling with user notifications.
  7. Future-Proofing: Embracing Modern Commanding is crucial for building future-proof Model-Driven Apps, as Microsoft's strategic focus and new feature development are centered around this Power Fx-driven approach.

Not read yet

Each section gets a ✓ as you scroll through it. Tap the button to jump to the next one.