这是我的第511篇原创文章,写于2024年10月12日。

以前的文章 通过调用Action/Custom API来触发Flow 提供了一种前端JavaScript代码通过调用Action或者Custom API调用Flow的方法,这个方法调用后就立即返回了,不会等到Flow运行完成,如果我要等到Flow运行完成呢?我这里介绍一种方法,这个方法与我之前的文章 定制现代命令按钮(Modern commands)示例 有关,不熟悉的这个现代命令按钮方法的请先阅读下我的文章。

这个方法的思路是,点击按钮打开一个Custom Page (不熟悉Custom Page的请参考我的文章 在Model-Driven App中使用自定义页面(Custom Page) ),在Custom Page中调用Flow。 

在现代命令栏可以执行的函数中,不包括Environment函数 (参考 Using Power Fx with commands ) 所以在使用Power Fx的时候不能直接调用Microsoft Dataverse中的Action或者Custom API来触发调用Flow。

命令栏可以用Power Fx的Navigate命令来打开一个Custom Page,但是面临两个问题,一个问题打开的这个Custom Page会覆盖当前页面,可能带来不好的体验,另外一个问题是 Commands using Power Fx for the action and/or visibility can't be converted to table or global scope at this time. 这句话翻译过来就是这个命令按钮定制只能生效在编辑这个命令按钮的app中,不能改成Table这种生效范围,实际上我们大部分场景要用的应该是Table这种生效范围。还有一个值得注意的是,使用Navigate打开Custom Page使用的是Custom Page的显示名称,而不是唯一名称,这和JavaScript打开Custom Page使用唯一名称不同。还有就是这个Custom Page需要添加到这个app中,否则打不开。为了规避这两个问题,我用命令调用JavaScript来弹出Custom Page到正中央,使用的代码参考如下:

var LY;
(function (LY) {
    class FlowInfo {
        static UpsertFlowInfo(formContext) {
            var pageInput = {
                pageType: "custom",
                name: "ly_upsertflowinfoapp_41ce6"
            };
            var navigationOptions = {
                target: 2,
                position: 1,
                width: { value: 600, unit: "px" },
                height: { value: 400, unit: "px" },
                title: "更新Flow信息表"
            };
            Xrm.Navigation.navigateTo(pageInput, navigationOptions)
                .then().catch(function (error) {
                Xrm.Navigation.openErrorDialog({ message: error.message });
            });
        }
    }
    LY.FlowInfo = FlowInfo;
})(LY || (LY = {}));


然后可以在打开的Custom Page的Screen的OnVisible执行类似如下的代码:

要运行的Flow.Run();Navigate(要打开列表界面的表);


当然这个Screen你可以放些文字提示操作正在进行中,简单效果如下:

另外一种前端按钮调用Flow的方法_Custom API


这样Flow运行完毕后会自动关闭这个Custom Page,返回到代码指定的表的主列表界面。据我观察,如果Flow运行时间过长,可能超过2分钟吧,这个界面会先关闭并打开指定表的主列表界面,后面的flow会继续运行。

因为按钮的Visibility我设置为Show,也就是一直显示,所以我可以将这个按钮的Scope改成Table级别,方法请参考 Scopes for modern commands 。简单来说就是将这个表的命令加入解决方案,以非托管解决方案导出,然后编辑其中的application.xml文件,将其中的类似如下的xml元素删除,再修改下appaction元素的uniquename属性值,保存后导入这个解决方案发布下就可以了。

<appmoduleid>
   <uniquename>demo_DemoFestApp</uniquename>
 </appmoduleid>


实际上我们按钮一般有可见性设置的,现代命令栏定制的可见性只能使用Power Fx,这样又导致了定制只能在定制进行的App中生效,这个真的有点坑,希望早日支持扩展到Table级别生效吧。

当然也可以通过JavaScript代码通过调用Action或者Custom API调用Flow的方法,类似代码如下:

var LY;
(function (LY) {
    class FlowInfo {
        static UpsertFlowInfo(formContext) {
            var requestInfo = {
                getMetadata: function () {
                    return {
                        boundParameter: null,
                        parameterTypes: {},
                        operationType: 0,
                        operationName: "ly_handleflowinfo"
                    };
                }
            };
            Xrm.WebApi.online.execute(requestInfo).then(function success(response) {
                if (response.ok) {
                    var confirmStrings = { text: "程序已经开始运行,请稍等三五分钟后再到当前页面查看结果。", title: "确认框" };
                    var confirmOptions = { height: 300, width: 440 };
                    Xrm.Navigation.openConfirmDialog(confirmStrings, confirmOptions);
                }
            }).catch(function (error) {
                console.log(error.message);
                var alertStrings = { confirmButtonLabel: "OK", text: "Operation Failed. " + error.message, title: "Error" };
                var alertOptions = { height: 300, width: 400 };
                Xrm.Navigation.openAlertDialog(alertStrings, alertOptions);
            });
        }
    }
    LY.FlowInfo = FlowInfo;
})(LY || (LY = {}));