In some cases, I want to start a Automate Flow from a Button in a Model Driven App. A really nice method is using the Ribbon Workbech. With this tool you can create a button in the top ribbon, or a sub view ribben which starts a Automate Flow. An explanation of this can be found here:

https://develop1.net/public/post/2019/12/21/smart-buttons-for-the-unified-interface

But what if you want a button on a other place in your screen (for example below a grid), like this:

For this solution I used the Action Button from Tanguy Touzard, which can be found here: https://github.com/MscrmTools/PCF-Controls

With this control I set up a button that starts the following javascript:

async function GetEnvironmentVariableValue (name) {

    let results = await Xrm.WebApi.retrieveMultipleRecords("environmentvariabledefinition", `?$filter=schemaname eq '${name}'&$select=environmentvariabledefinitionid&$expand=environmentvariabledefinition_environmentvariablevalue($select=value)`);

    if (!results || !results.entities || results.entities.length < 1) return null;
    let variable = results.entities[0];
    if (!variable.environmentvariabledefinition_environmentvariablevalue || variable.environmentvariabledefinition_environmentvariablevalue.length < 1) return null;

    return variable.environmentvariabledefinition_environmentvariablevalue[0].value;
}

async function buttonFlow(executionContext,flowName,confirmText){

    debugger;

    var attribute = executionContext.getEventSource();
    attribute.setValue(null);
    attribute.setSubmitMode("never");
    var formContext = executionContext.getFormContext();

    let results = await Xrm.Navigation.openConfirmDialog({ text:confirmText, title:"Starting flow" }, { height: 200, width: 450 })
    if (!results.confirmed) return;

    formContext.ui.setFormNotification("One moment please, flow is being started", "INFO", "FlowNotify");

    var flowUrl = await GetEnvironmentVariableValue(flowName);

    if(flowUrl != "undefined" && flowUrl != null) {

        var input = JSON.stringify({
            "id": formContext.data.entity.getId().replace("{", "").replace("}", "")
        });
        var req = new XMLHttpRequest();
        req.open("POST", flowUrl, true);
        req.setRequestHeader('Content-Type', 'application/json');
            

        req.onreadystatechange = function () {
                if (this.readyState === 4) { 
                    req.onreadystatechange = null;
                    if (this.status === 200) {
                        var result = this.response; 
                        Xrm.Navigation.openAlertDialog({ confirmButtonLabel: "Ok", text: result, title: "Success" }, { height: 120, width: 260 });
                    }
                    else if(this.status === 400){
                        var result = this.response; 
                        Xrm.Navigation.openAlertDialog({ confirmButtonLabel: "Ok", text: result, title: "Failed" }, { height: 120, width: 260 });
                    }
                }
                formContext.ui.clearFormNotification("FlowNotify");
            };  
            

        req.send(input);

    }
}

function buttonCreateInvoice(executionContext){

    buttonFlow(executionContext,"os_varURLInvoiceFlow","Are you sure you want to create an invoice?");

}

Disclaimer again: I’m definitely no Javascript coding expert, so if you have any input how to do this better. Please let me know…

When the button is pressed (OnChange event), the function buttonCreateInvoice is being started. This function buttonFlow is called where the URL of the flow is being called. Also the return text from the flow is displayed as succes or failed description.

The URL of the flow is defined in an environement variable. For this I used a script that was published by Eric Regnier in a blogpost: https://powerusers.microsoft.com/t5/Microsoft-Dataverse/Get-Value-of-Environment-Variable-using-JavaScript/td-p/577219