[Experimental Feature] Call Dataverse actions directly in Power Fx

March 1, 2023 1 comment

In one of my previous articles, I’ve explained the steps to call the Dataverse Custom API from Canvas App using Power Automate cloud flow.

Recently a new experimental feature Call Dataverse actions directly in Power Fx released using which makers can now directly invoke a Dataverse Custom API within a Power Fx formula.

About the feature:

  • Power Apps will support the ability to directly call synchronous Dataverse actions without having to create a Power Automate Flow.
  • For apps that need to call many Dataverse actions, this will provide a significant performance boost.
  • It’ll be much easier to directly call Dataverse actions from the new Power Fx language element Environment.
  • The Environment object allows authors to dot into actions available in the environment. 
  • Its currently an Experiment feature and can be enabled from Canvas Studio -> Settings -> Upcoming features -> Experimental. Turn on the ‘Enable access to Microsoft Dataverse actions’ toggle.

In this article lets learn how to call the Custom API directly in Power Fx formula without the need of Power Automate flow. But first lets get familiar with our Custom API.

Custom API Details:

  • I already have a Custom API by name ‘cat_onboardcustomer‘ (Refer article for steps to create Custom API from scratch).
  • cat_onboardcustomer‘ API has a request Parameter by name ‘cat_customername‘ of type ‘String’.

Now that we know our Custom API, lets learn how to call the API in Power Fx by building a simple canvas app.

Steps to call Dataverse actions directly from Power Fx:

  • Create a Canvas App.
  • Open Settings -> Upcoming features -> Experimental. Turn on the ‘Enable access to Microsoft Dataverse actions’ toggle.
  • By enabling, A new Power Fx ‘Environment’ language object will be available under ‘Data sources’.
  • From the Canvas App, search for the ‘Environment‘ data source as shown below.
  • Double click and add the Environment data source.
  • Add a button on to the Canvas App and ‘OnSelect’ event, write the following Power Fx formula.
    • In the formula, we are calling cat_onboardcustomer API using ‘Environment’ data source.
    • We are also passing cat_customername request parameter in json format.

Environment.cat_onboardcustomer({cat_customername: "Calling API from Power Fx is awesome"})
  • That’s all needed. Play the App and click the button and you should see the ‘Account’ created with the name “Calling API from Power Fx is awesome”.

🙂

Advertisement
Categories: Canvas Apps Tags: ,

[Quick Tip] Dataverse Web API | Handling special characters in Filter query

February 28, 2023 1 comment

In this quick tip, lets see how to handle special characters while querying the Dataverse Web API.

Assume that you have a Dataverse Team with name CoE&Feb&Makers as below and you would want to query the Team by ‘Team Name’ using Dataverse Web API.

Query Dataverse Web API:

  • When you hit the URL, you will get an exception that ‘The query parameter is not supported‘. This is because the team name CoE&Feb&Makers is having & symbol, which is not supported.
  • To fix this, you need to encode the team’s name. You can use online editor to encode, if you are querying the Web API from browser.
  • Now use the encoded value CoE%26Feb%26Makers in the Filter and you should get the result.

🙂

Canvas App | Nested Galleries using polymorphic lookup Filter

February 27, 2023 Leave a comment

In this article, lets learn how to apply a filter on polymorphic lookup in Canvas App.

What is a polymorphic lookup in Dataverse:

  • Dataverse supports polymorphic lookups, which can refer to a record from any table in a set.
  • For example, ‘ParentCustomerID‘ (i.e., Display name is ‘Company Name’) column in the Contact table is a polymorphic lookup, where you can select either an Account or Contact record.
  • In below example, there are Contacts linked Accounts via ‘Company Name’ polymorphic lookup.

Now that we know what is a Polymorphic lookup in Dataverse, lets learn how to apply filters on polymorphic lookup in Canvas app by building a simple application.

Build a Canvas App using Nested Galleries and polymorphic lookup Filter:

In this sample Canvas App, I am going to add a ‘Contacts’ gallery inside an ‘Accounts’ gallery and show only those ‘Contacts’ linked to the ‘Account’ in the gallery row. Lets get started.

  • Create a new Canvas App.
  • On the form, add a Blank Flexible Height Gallery control ‘galAccounts‘ to the form and set Datasource as ‘Accounts’ Dataverse table.
    • You can add any Gallery type of your choice but the Flexible Height Gallery control’s row height auto expands as per the row’s content size.
  • Now, select the galAccounts and add a new gallery ‘galContacts‘ pointing to ‘Contacts’ Dataverse table as shown below.
  • This is how you configure nested galleries, in our case we have the ‘Contact’ gallery (i.e., galContacts) inside the ‘Accounts’ gallery (i.e., galAccounts).
  • Preview the App and we would get all the available Contacts in Dataverse in each row of the galAccounts.
  • But this is not what we want. We need to see only those Contacts linked to Account (i.e., ‘Contoso 1’ account row should only show ‘Contoso 1 – Contact 1’, ‘Contoso 1 – Contact 2′ and ”Contoso 1 – Contact 3’ contacts as per our available data).
  • Lets solve the final piece of the puzzle of applying the filter on ‘Contacts’ by ‘Company Name’ column which is a polymorphic lookup.
  • Select the galContacts gallery control, and in ‘Items’ property write following formula.
Filter(
    Contacts,
    AsType(
        'Company Name',
        [@Accounts]
    ).Account = ThisItem.Account
)
  • Now play the App and you should see the filtered Contacts.
  • You can also add a toggle button to show/hide the galContacts for collapse effect.
More about the formula:
  • If you notice, the formula has AsType function. Because the ‘Company Name’ column in the Contact table is a polymorphic lookup, which accepts either an Account or Contact record, we have to use AsType function to specify the table type we are filtering.
  • In our scenario, we need to filter ‘Contacts’ based on ‘Company Type’ column which holds a specific Account from galAccounts gallery.
  • So in the Filter formula we have used AsType function with 1st parameter as ‘Company Name’ and 2nd parameter as [@Accounts] which refers to the ‘Account’ TableType.

We also have IsType function, which tests whether a record reference refers to a specific table type. The function returns a Boolean TRUE or FALSE.

  • Following formula checks whether the ‘Company Name’ column of Contact table holds either an Account record or Contact type record.
If( IsType( ThisItem.'Company Name', Accounts ),
    AsType( ThisItem.'Company Name', Accounts ).'Account Name',
    AsType( ThisItem.'Company Name', Contacts ).'Full Name'
)

🙂

Canvas App | Power automate | Read and preview Dataverse ‘File’ column content

February 21, 2023 Leave a comment

In this article, I am going demonstrate how to read and preview the text content of Dataverse ‘File’ column by using Canvas App and Power automate flow.

Scenario:

To explain the read and previewing the Dataverse file column, I’ve taken following scenario.

Note : Approach in this article only works for plain text files but not for Doc,Docx,Pdf file types.

  • Create a table ‘Preview Files’ in Dataverse
  • Add a ‘File’ column by name ‘Preview Attachment‘ to upload text files.
  • Build a Canvas App, to show the ‘Preview File’ records in a gallery and on selection of a record, read the content of the ‘Preview Attachment’ column’s file and display.

In this article, I will focus more on Power Automate side of things on how the flow can be used to retrieve the file content and pass it back to Canvas App. Lets get started.

Steps to create Canvas App:

I will not be explaining steps to create Canvas app from scratch. For our scenario, at the high-level.

  • Create a new Canvas App and add a Vertical Gallery control by name galPreviewFiles.
  • Add ‘Preview Files’ Dataverse table as Datasource of the galPreviewFiles.
  • Add a Text Label control to show the preview of File content.
  • Canvas App looks as below.

Steps to build Power automate flow to fetch the Dataverse file content:

As we will be triggering flow from Canvas app by passing parameters back and forth, create a new flow from Canvas app studio by

  • From Canvas App studio, create a new flow from blank as shown below.
  • In the flow editor, add Initialize a variable control and name it as ‘varPreviewFileId’.
    • In the ‘Name’ parameter, provide name as previewField and in the ‘Value’ parameter, select ‘Ask in PowerApps’.
      • From Canvas App we will pass the selected Preview Files table’s record id.
      • We need ‘previewField ‘ variable to capture the passed id from the Canvas app.
  • Next add Download a file or an image control to download the content of ‘Preview Attachment‘ file column of the ‘Preview Files‘ table.
    • Set ‘Row ID’ as previewField.
    • Set ‘Column name’ as ‘Preview Attachment‘, which is the file column of the ‘Preview Files‘ Dataverse table.
  • Download a file or an image control provides the Response as below.
    • Response contains ‘$content-type’ and ‘$content’ parameters.
    • ‘$content’ contains the Base64 format of ‘Preview Attachment‘ file column content.
  • So in the next step, we need to convert the ‘$content’ value from Base64 to plain text.
  • Add Compose action and in the ‘inputs’ parameter write following formula using base64ToString expression.
    • base64ToString(outputs(‘DownloadPreviewFileAttachment’)?[‘body’]?[‘$content’])
    • Here DownloadPreviewFileAttachment is the name of Download a file or an image control added in previous step.
  • That’s it, we have the logic to read the ‘Preview Attachment‘ file column content and convert to string.
  • As a last step, we will pass the ‘Preview Attachment‘ file column content back to Canvas app.
  • Add Respond to a PowerApp or flow control to send the response back to Canvas app.
    • Add an output parameter by name ‘FileContent’ and in the Value select the Outputs of ‘fileContent’ compose action added in previous step.
  • Provide the name of the flow.
    • I have named my flow as FetchDataverseFileColumn.
  • Save the flow.

Trigger flow from Canvas App:

Now that we have Canvas App and Cloud flow, we simply need to trigger the flow from Canvas App.

  • Use following formula to fetch the file content of selected galPreviewFiles gallery control item.
    • Note that, I have a button ‘btnPreview’ in my galPreviewFiles gallery control. So I am triggering formula on ‘OnSelect’ of ‘btnPreview’ button.
UpdateContext({fileContent: FetchDataverseFileColumn.Run(galPreviewFiles.Selected.'Preview File').filecontent});
  • In the formula,
    • I am calling FetchDataverseFileColumn.Run() to call the FetchDataverseFileColumn flow and also passing the galPreviewFiles selected record’s Id.
    • Capturing the Output of the FetchDataverseFileColumn flow in to fileContent variable.
  • Set the fileContent variable to the Text Label control.

That’s all. Save and Publish your Canvas app.

Disclaimer :
  • As mentioned in the Notes, approach in this article only works for plain text files but not for Doc,Docx,Pdf file types.
  • Purpose of this article is to make aware of calling flows from Canvas app and usage of Download a file or an image control.

🙂

Pac cli | Install and launch Plugin Registration, Package Deployer and Configuration Migration tools

February 21, 2023 1 comment

Conventionally tools like Plugin Registration Tool (PRT) can be download from NuGet. Downloading and installing from NuGet is tedious because of following reasons:

  • Difficult to launch the tools. Because the downloaded PRT gets stored in your local directory, to launch the tool, you have to go that folder and look for the .exe file to open.
  • Difficult to upgrade the version. To upgrade the version of the tools, you have to download latest version form NuGet to your local storage.

Using Power Platform CLI, the tools download and launch process has been super simplified. Let me walk you through the process of installing and launching the tools using Power Platform CLI.

Lets first start with the basics.

What is Power Platform CLI

  • Microsoft Power Platform CLI is a simple, one-stop developer CLI that empowers developers and ISVs to perform various operations in Microsoft Power Platform.
  • Follow these steps to install.
  • Once you install, run pac in the command prompt and you should see screen as below.

Steps to install the tools using Power Platform CLI

Once you install the Power Platform CLI in your machine, open the Visual Studio Command Prompt (You can also use VSCode).

  • Run pac tool list command which lists the tool installation details.
  • If you notice the above screen, ‘Installed’ value is ‘No’, which means I don’t have tools installed yet.
Install/Uninstall Plugin Registration Tool (PRT):
  • Now, lets install Plugin Registration Tool (PRT). Its super simple.
  • Execute pac tool prt command. PRT tool gets installed and launched in a blink.
  • If you run the pac tool list command again, you should see the PRT installed status as Yes.
Launch the Plugin Registration Tool

Once you install the PRT to launch from the next time, you have 2 options.

  • Open the PRT App from the ‘Start’.
  • Open the Visual Studio Command Prompt and run pac tool prt command

Steps to install Package Deployer and Configuration Migration tools:

To install the Package Deployer (PD) and Configuration Migration (CMT) tools, follow the same steps we used for PRT. We just need to change the commands.

That’s how tools can be seamlessly downloaded and launched using the Power Platform CLI.

🙂

Categories: Power Platform Tags: , ,

Dataverse File Download error | Feature ‘target-typed object creation’ is not available in C# 7.3

February 17, 2023 Leave a comment

I was trying to download the Dataverse File using the code snippet provided in official documentation.

Following is the snippet and I got the Feature ‘target-typed object creation’ is not available in C# 7.3 compilation error.

Reason:

  • Target-typed new expressions has been introduced in C# 9.0 using which we do not require type specification for constructors when the type is known.
  • Since I was not having C# 9.0 I was getting the compilation error.

Fix:

  • Fix is simple, we need to replace
InitializeFileBlocksDownloadRequest initializeFileBlocksDownloadRequest = new()
            {
                Target = entityReference,
                FileAttributeName = fileAttributeName
            };sds

with

            InitializeFileBlocksDownloadRequest initializeFileBlocksDownloadRequest = new InitializeFileBlocksDownloadRequest
            {
                Target = entityReference,
                FileAttributeName = fileAttributeName
            };

and replace

            List<byte> fileBytes = new();

with

            List<byte> fileBytes = new List<byte>();
Modified code snippet:
    /// <summary>
    /// Downloads a file
    /// </summary>
    /// <param name="service">The service</param>
    /// <param name="entityReference">A reference to the record with the file column</param>
    /// <param name="fileAttributeName">The name of the file column</param>
    /// <returns></returns>
    private static byte[] DownloadFile(
                IOrganizationService service,
                EntityReference entityReference,
                string fileAttributeName)
    {
        InitializeFileBlocksDownloadRequest initializeFileBlocksDownloadRequest = new InitializeFileBlocksDownloadRequest()
        {
            Target = entityReference,
            FileAttributeName = fileAttributeName
        };

        var initializeFileBlocksDownloadResponse =
              (InitializeFileBlocksDownloadResponse)service.Execute(initializeFileBlocksDownloadRequest);

        string fileContinuationToken = initializeFileBlocksDownloadResponse.FileContinuationToken;
        long fileSizeInBytes = initializeFileBlocksDownloadResponse.FileSizeInBytes;

        List<byte> fileBytes = new List<byte>();

        long offset = 0;
        long blockSizeDownload = 4 * 1024 * 1024; // 4 MB

        // File size may be smaller than defined block size
        if (fileSizeInBytes < blockSizeDownload)
        {
            blockSizeDownload = fileSizeInBytes;
        }

        while (fileSizeInBytes > 0)
        {
            // Prepare the request
            DownloadBlockRequest downLoadBlockRequest = new()
            {
                BlockLength = blockSizeDownload,
                FileContinuationToken = fileContinuationToken,
                Offset = offset
            };

            // Send the request
            var downloadBlockResponse =
                     (DownloadBlockResponse)service.Execute(downLoadBlockRequest);

            // Add the block returned to the list
            fileBytes.AddRange(downloadBlockResponse.Data);

            // Subtract the amount downloaded,
            // which may make fileSizeInBytes < 0 and indicate
            // no further blocks to download
            fileSizeInBytes -= (int)blockSizeDownload;
            // Increment the offset to start at the beginning of the next block.
            offset += blockSizeDownload;
        }

        return fileBytes.ToArray();
    }

🙂

Power Automate Cloud Flow | ‘Correct to include a valid reference’ error

February 16, 2023 Leave a comment

Other day while working on error handling scenario in my Cloud Flow, my Flow Checker given me following error.

Correct to include a valid reference to ‘Data Operation Divide‘ for the unput parameters(s) of action ‘Set_Error_Message‘.

Error from Flow checker

Lets see the reason and fix for this error.

Reason:

  • In my flow, I am capturing the error message of my Compose action by name Data Operation Divide in my Set Variable action by name Set Error Message.
  • My Data Operation Divide compose action does a simple division operation of ‘numA’ and ‘numB’ values using div function.
  • My Set Error Message action configured to run only when Data Operation Divide compose action fails.
  • Set Error Message action ‘Value’ configured with actions expression to read the Data Operation Divide action’s error.
    • The expressions used is actions(‘Data Operation Divide‘)?[‘error’]?[‘message’]
  • Everything does looks fine right?. Then where is the error?.
  • The answer is actions expression does not accept spaces in the action name. In my case, action name is ‘Data Operation Divide‘ which has got spaces.
  • Hence the ‘Flow Checker’ showing Correct to include a valid reference to ‘Data Operation Divide‘ for the unput parameters(s) of action ‘Set_Error_Message error.

Fix:

  • In the actions expression of Set Error Message action ‘Value’ parameter, replace spaces with underscore(_).
    • Formula looks as below actions(‘Data_Operation_Divide‘)?[‘error’]?[‘message’]
  • Notice the ‘Flow Checker’ and error is gone.
  • Run the flow with ‘numA’ as 10 and ‘numB’ as 0.
  • And the ‘Set_Error_Message error action show the error message.
  • So the bottom line, actions expression does not accept spaces in the action name.

Please refer my previous blog post with detailed explanation of error handling in Power automate flow.

🙂

[Step by Step] Create and call Global Custom API from Canvas App using Power Automate with Error Handling

February 15, 2023 4 comments

In this article, lets learn how to create a Custom API and trigger using Power Automate Cloud Flow along with Error Handling from a Canvas App.

What is a Custom API:

  • Using Custom APIs we can create our own APIs in Dataverse.
  • We can consolidate one or more operations into a Custom API which can called from either code or from Power Automate.
  • For example, you can create a Custom API called “OnBoardNewCustomer’, where you can have following operations.
    • Create a new ‘Account’ record.
    • Create a new ‘Appointment’ record scheduled a week from now.
    • Send an Email notification.

Now lets get started with Custom API creation. I am going to use ‘Onboard Customer’ scenario to explain the Custom API creation. I will be using 2 operation in my Custom API.

  • Create an Account record by reading ‘Name’ as input parameter.
  • Create an Appointment record for the newly created Account and schedule at 7 days from now.

Create a Custom API:

There are several ways you can create a custom API documented here. In this article, I will be taking 2 step approach.

  • Write a C# plugin class file with logic and register using Plugin Registration Tool (PRT).
  • Create a Custom API using forms from Power Apps Maker portal and link the plugin created in previous step.

Steps to create Custom API in plugin class and register using PRT:
  • Open Visual Studio and create a plug-in project as detailed in this document here.
  • Add an .snk file to the project.
  • Create a new plugin class file with logic to create Account and Customer.

  • Final code in the class file looks as below.
        public void Execute(IServiceProvider serviceProvider)
        {
            var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

            if (context.MessageName.Equals("cat_onboardcustomer") && context.Stage.Equals(30))
            {
                try
                {
                    // Read the input parameter
                    string inputParamCustomerName = (string)context.InputParameters["cat_customername"];

                    if (!string.IsNullOrEmpty(inputParamCustomerName))
                    {
                        IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                        IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

                        // Create Account Record
                        var entAccount = new Entity("account");
                        entAccount["name"] = inputParamCustomerName;
                        var accountId = service.Create(entAccount);

                        // Create Appointment Record
                        var entAppointment = new Entity("appointment");
                        entAppointment["subject"] = $"Meeting with Customer {inputParamCustomerName}";
                        // Set the start and end times for the entAppointment 7 days fro now
                        entAppointment["scheduledstart"] = DateTime.Now.AddDays(7).AddHours(1);
                        entAppointment["scheduledend"] = DateTime.Now.AddDays(7).AddHours(2);
                        // Set the related account for the entAppointment
                        entAppointment["regardingobjectid"] = new EntityReference("account", accountId);
                        var appointmentId = service.Create(entAppointment);
                    }
                }
                catch (Exception ex)
                {
                    throw new InvalidPluginExecutionException("An error occurred in cat_onboardcustomer.", ex);
                }
            }
        }
  • Build the project and register the plugin assembly using PRT.
  • Post registration it should look as below from PRT.

Now that we completed the step 1 of creating and registering plug-in class file. Lets proceed with step 2 where we will create a Custom API entry.

Create a Custom API using forms from Power Apps Maker portal:
  • Connect to Power Apps maker portal.
  • Create a new solution or open any existing solution.
  • Click on New -> More -> Other -> Custom API
  • It opens up a new ‘Custom API’ form and fill the details.
    • To understand the columns in depth, refer here.
    • What is important for this example are:
      • Unique Name : Unique name for the custom API. (Its cat_onboardcustomer we used in our plug-in class)
      • Name : The primary name of the custom API.
      • Plugin Type : Plugin we registered in previous section.
  • Save and Close.
  • As we need to pass a parameter to our ‘Custom API’, next add a new ‘Custom API Request Parameter’.
  • Fill the details by selecting ‘Custom API’ we created in previous step and ‘Unique Name’ as cat_customername, which we used in our plugin class.
  • Save and Close.

With this we successfully created ‘Custom API’ along with an input parameter. Lets see how to trigger API using Power Automate Cloud Flow from a Canvas App.

Steps to trigger Custom API from Canvas App:

  • Create a new Canvas App.
  • Go to Flows tab and click on ‘Create new flow’ and choose ‘Create from blank’.
  • In the flow designer, add ‘Initialize Variable’ action and rename to ‘varCustomerName’. In the ‘Value’ select ‘Ask in PowerApps’.
  • Next add Dataverse ‘Perform an unbound action‘ action which helps us to trigger our ‘Global’ custom API.
    • Select ‘Action Name’ as our Custom API name cat_onboardcustomer
    • In the cat_customername pass ‘Customer Name’ which was the variable declared in above step.
  • If you dont want exception handling, you can save the flow which can trigger the cat_onboardcustomer.

Exception Handling:

Lets learn a basic error handling. Please note that you can use ‘Scope’ for more complex scenarios but for basic exception handling following process should suffice.

  • Add another ‘Initialize Variable’ action and rename it to ‘varExceptionDetails’ and set Type as ‘String’.
  • Rename the ‘Perform an unbound action’ to ‘InvokeOnboardAPI’
  • Add a ‘Set Variable’ action ‘setExceptionDetails’ to capture the exception.
  • Select the Name as ‘ExceptionDetails‘ and click on ‘Configure run after’. (This is needed as we want this ‘setExceptionDetails’ to execute even the above ‘InvokeOnboardAPI’ action fails or timeout.
  • Select following options.
  • In the ‘Value’ select ‘Expression’ and paste following expression.
    • actions(‘InvokeOnboardAPI’)?[‘outputs’]?[‘body’]?[‘error’]
  • Finally to send the response from flow to Canvas app, add ‘Respond to a PowerApp of flow’ action and click on ‘Configure run after’, select following options and click ‘Done’.
  • and define an output variable OnboardflowResponse and set the value as ExceptionDetails.
  • Save the flow and you should see the flow in your Canvas App.
  • To trigger the flow, add a button to the screen and OnSelect write following formula.
Notify("Triggering User Onboard...");
UpdateContext({ResponseOnBoardFlow: CustomerOnboardFlow.Run("Rajeev Pentyala").onboardflowresponse});
If(
    ResponseOnBoardFlow = "Success",
    Notify("Customer onboarded successfully."),
    Notify("Error while onboarding. Details - " & ResponseOnBoardFlow)
)

  • Run the App and click the button.
  • Open Dataverse and you should see the new Account and Appointment records. You can also check the flow run history.

🙂

[Quick Tip] Canvas App | Add Emojis

February 14, 2023 Leave a comment

Do you know that we can add Emojis to the controls and screens text properties in Canvas Apps. In this quick tip article lets learn how to add Emojis.

Adding Emojis:

  • We can add Emoji to the ‘App name’ of the App. While creating a new Canvas App, in the ‘App name’, press Windows Key (🪟) + Dot (.) and pick the Emoji you wish and proceed with creation.
  • On the screen, add a Label control and in the ‘Text’ property you can add Emojis simply by hitting Windows Key (🪟) + Dot (.) .
  • Play the App and you should see as below.

🙂

Categories: Canvas Apps Tags: ,

Model Driven App | Command Bar | Power Fx formula examples

February 9, 2023 Leave a comment

I’ve written an introductory article on Command Bar when the feature was in preview state. Now that the Command Bar evolved with Power Fx, lets learn few scenarios using Command Bar with Power Fx.

I am taking a scenario of Cloning a record with following design:

  • Add new Command button on Command Bar
  • On ‘OnSelect’, write Power Fx Patch formula to create a new record from existing record.
  • Write a Visibility rule, to display the Command button only on ‘Edit’ form.

Lets get started.

Add a new Command button and implement Clone functionality:

  • Open the Model Driven App in editor and select a table which you would want to place the Clone button. click on ‘Edit command bar’.
  • Selected ‘Main form’ as we are going to add ‘Clone’ button on form.
  • Add a new ‘Command’ button and provide details like Label, Icon, etc…
  • We need to write ‘Power Fx’ formula on ‘OnSelect’ event of the command button.
  • We can write the formula in the formula text box at the top but its not intuitive. One option is to write the formula by clicking on ‘Open component library’, which opens up Canvas app editor.
  • Click on ‘Open component library’.
  • Point to be noted is every time you add a new Command button, it creates a component in the background.
  • Once the ‘Command Library’ window opens up, under ‘Tree View’, you can see a separate component for each command button you have in your MDA.
  • Coming back to our Clone scenario, select the ‘Clone Customer_1’ component and on ‘OnSelect’ event, write the PowerFx formula to clone the current record.
    • I am using Patch function with Defaults(Customers) which creates a new record.
Notify("Cloning the Customer...");

Patch(

    Customers,

    Defaults(Customers),

    {

        Name: "Clone - " & Self.Selected.Item.Name,

        Gender: [@Gender].Male,

        'Date of Birth': Self.Selected.Item.'Date of Birth',

        'Mobile Number': Self.Selected.Item.'Mobile Number'

    }

);

Notify("Cloning completed successfully !!!");
  • Click on ‘Publish’ icon and close the window.
  • Come back to the MDA editor and you would see the clone Power Fx formula prepared in Components library screen.
  • Click on ‘Play’ to test the ‘Clone Customer’ button in your MDA.
  • Open a Customer record and click on ‘Clone Customer’ button.
  • Up on successful clone, you would get the ‘Cloning completed successfully’ notification and you can even open the new cloned record.

Command Visibility Formula:
  • Now that we achieved the clone functionality, lets add a validation by showing the ‘Clone Customer’ command only on Edit form.
  • Go back to MDA editor and select the ‘Clone Customer’ command and set Visibility as ‘Show on condition from formula’.
  • In the formula, specify formula as
Self.Selected.State = FormMode.Edit
  • Publish and Play the App and you would see the ‘Clone Customer’ button only on edit form but not on create form.

🙂