在模型驱动应用中编写第一个客户端脚本

了解如何在模型驱动应用中编写第一个 JavaScript 客户端脚本。 本演练演示如何创建脚本、将其作为 Web 资源上传、将其附加到表单和列事件,并对其进行测试,以便你可以向表单添加自定义业务逻辑。

目标

完成本演练后,了解如何在模型驱动应用中使用 JavaScript 代码。 此过程涉及以下高级步骤:

  • 找到或创建一个解决方案,将你的工作添加到其中。
  • 编写 JavaScript 代码以解决业务问题
  • 将代码作为 Web 资源上传
  • 将 Web 资源关联到窗体
  • 配置表单和字段事件
  • 测试代码

注释

若要查看并验证已完成的演练,请下载 JavaScriptWebResourceExampleSolution_1_0_managed.zip。 安装此托管解决方案并查看它包含的帐户管理应用。

步骤 1:查找或创建解决方案

使用解决方案将自定义项从一个环境传输到另一个环境。 在开发环境中编写和测试 JavaScript 代码,作为非托管解决方案的一部分。 完成测试后,将解决方案导出为托管解决方案,并将其导入或安装到生产环境中。

现有解决方案可能已可供你使用。 想要使用脚本自定义的模型驱动应用应已是解决方案的一部分。 可以编辑该解决方案,也可以创建依赖于另一个现有解决方案的新解决方案。

创建新解决方案

  1. 转到 Power Apps。

  2. 在左侧导航窗格中,选择解决方案,然后选择新建解决方案。

  3. 在浮出对话框中,输入显示名称、名称和发布服务器。

    大多数公司都有一个他们始终使用的现有发布者。 使用该发布者。 如果您是第一位操作者,请创建您自己的发布者。

    选择 “新建发布服务器 ”以打开 “新建发布服务器 ”对话框。 在本操作指南中,请使用具有以下定义的发布者:

    “新建Publisher”窗体的屏幕截图,其中包含示例Publisher的信息。

    请注意 前缀 值。 此值应标识你的公司。 在本例中,请使用 example。

    这是您在本演练中使用的解决方案。

    第一个客户端脚本解决方案的解决方案表单的屏幕截图。

  4. 找到或向解决方案添加模型驱动应用。

    新解决方案不包含任何模型驱动应用。 需要添加现有的模型驱动应用或创建新的应用。

    注释

    为便于本操作指南的演示,请确保应用程序包含“Account”表。 下面的脚本和说明基于“Account”表的表单中的字段。

    选项 A:将现有模型驱动应用添加到解决方案

    1. 在解决方案中,选择“ 添加现有的>应用>模型驱动应用”。

    用于将现有模型驱动应用添加到解决方案的菜单的屏幕截图。

    1. 选择现有应用,然后选择“ 添加”。

    选项 B:在解决方案中创建新的模型驱动应用

    在解决方案中,选择“新建>应用>”。

    请参阅 生成第一个模型驱动应用 教程。 创建包含帐户表的应用。

步骤 2:编写 JavaScript 代码

第一步是使用客户端脚本确定要解决的业务问题。 确定问题时,请编写包含解决业务问题的自定义业务逻辑的 JavaScript 代码。

模型驱动应用不提供 JavaScript 编辑器。 使用专门支持编辑 JavaScript 文件功能的外部编辑工具,例如 Notepad++、Visual Studio Code 或 Microsoft Visual Studio。

本演练使用以下 JavaScript 代码:

// Define a unique namespace for the sample library.
window.Example ??= {};

(() => {
    const notificationId = "_myUniqueId";
    const currentUserName = Xrm.Utility.getGlobalContext().userSettings.userName;
    const message = `${currentUserName}: Your JavaScript code in action!`;

    // Code to run in the form OnLoad event
    window.Example.formOnLoad = (executionContext) => {
        const formContext = executionContext.getFormContext();

        // Display the form level notification as an INFO
        formContext.ui.setFormNotification(message, "INFO", notificationId);

        // Wait for 5 seconds before clearing the notification
        window.setTimeout(
            () => formContext.ui.clearFormNotification(notificationId),
            5000
        );
    };

    // Code to run in the column OnChange event
    window.Example.attributeOnChange = (executionContext) => {
        const formContext = executionContext.getFormContext();

        // Automatically set some column values if the account name contains "Contoso"
        const accountName = formContext.getAttribute("name").getValue();
        if (accountName?.toLowerCase().includes("contoso")) {
            formContext.getAttribute("websiteurl").setValue("https://www.contoso.com");
            formContext.getAttribute("telephone1").setValue("425-555-0100");
            formContext.getAttribute("description").setValue("Website URL, Phone and Description set using custom script.");
        }
    };

    // Code to run in the form OnSave event
    window.Example.formOnSave = () => {
        // Display an alert dialog
        Xrm.Navigation.openAlertDialog({ text: "Record saved." });
    };
})();

将此代码复制到文本文件中,并将其另存为 form-script.js。

详细的代码说明

让我们详细查看代码:

  • 定义命名空间:代码首先定义自定义脚本的命名空间。 最佳实践是始终创建具有命名空间的 JavaScript 库,以避免您的函数被另一个库中的函数覆盖。

    window.Example ??= {};
    

    在这种情况下,可以使用此库中定义的所有函数作为 Example.[functionName]. 选择与解决方案发布者名称匹配的命名空间。

  • 定义常量:以下部分定义要在脚本中使用的一些常量。 可以使用 Xrm.Utility.getGlobalContext 方法全局访问上下文信息。

    const notificationId = "_myUniqueId";
    const currentUserName = Xrm.Utility.getGlobalContext().userSettings.userName;
    const message = `${currentUserName}: Your JavaScript code in action!`;
    
  • 在 OnLoad 事件上执行的函数:本节包含在帐户窗体加载时执行的函数。 例如,创建新帐户记录或打开现有帐户记录时。

    该 Example.formOnLoad 函数使用 executionContext 参数获取 formContext 对象。 稍后使用表单事件附加代码时,请选择将 执行上下文 传递给此函数的选项。

    此函数使用 formContext.ui.setFormNotification 方法显示窗体级别通知。

    最后,此函数使用 JavaScript setTimeOut 方法 延迟 formContext.ui.clearFormNotification 方法的执行,以在 5 秒后清除通知。

    // Code to run in the form OnLoad event
    window.Example.formOnLoad = (executionContext) => {
        const formContext = executionContext.getFormContext();
    
        // Display the form level notification as an INFO
        formContext.ui.setFormNotification(message, "INFO", notificationId);
    
        // Wait for 5 seconds before clearing the notification
        window.setTimeout(
            () => formContext.ui.clearFormNotification(notificationId),
            5000
        );
    };
    
  • 在 OnChange 事件上执行的函数:将 Example.attributeOnChange 函数与帐户窗体中的 “帐户名称 ”列相关联,以便 仅在 更改帐户名称值时执行该函数。

    该函数在帐户Contoso中执行对name的不区分大小写的搜索,如果找到,则为账户表单中的websiteurl、telephone1和description列设置值。

    // Code to run in the column OnChange event
    window.Example.attributeOnChange = (executionContext) => {
        const formContext = executionContext.getFormContext();
    
        // Automatically set some column values if the account name contains "Contoso"
        const accountName = formContext.getAttribute("name").getValue();
        if (accountName?.toLowerCase().includes("contoso")) {
            formContext.getAttribute("websiteurl").setValue("https://www.contoso.com");
            formContext.getAttribute("telephone1").setValue("425-555-0100");
            formContext.getAttribute("description").setValue("Website URL, Phone and Description set using custom script.");
        }
    };
    
  • 在 OnSave 事件上执行的函数:该 Example.formOnSave 函数使用 Xrm.Navigation.openAlertDialog 方法显示警报对话框。 此对话框显示一条消息,其中包含 “确定 ”按钮。 用户可以通过选择 “确定”关闭警报。

    注释

    此函数不使用执行上下文,因为 Xrm.Navigation 。方法不需要它。

    // Code to run in the form OnSave event
    window.Example.formOnSave = () => {
        // Display an alert dialog
        Xrm.Navigation.openAlertDialog({ text: "Record saved." });
    };
    

步骤 3:将代码作为 Web 资源上传

代码准备就绪后,请将其上传到解决方案中。

  1. 在解决方案中,选择“ 新建>更多>Web 资源”。

    用于向解决方案添加新 Web 资源的菜单的屏幕截图。

  2. 在“ 新建 Web 资源 ”对话框中,选择 “选择文件 ”,然后选择 form-script.js 之前保存的文件。

  3. 输入显示名称、名称,以及可选的说明。 确保类型为JavaScript(JS)。

    用于创建示例表单脚本的“新建 Web 资源”对话框的屏幕截图。

    注释

    • 名称具有与解决方案发布者自定义前缀匹配的前缀。 还有其他方法可以创建 Web 资源,但通过这种方式创建 Web 资源可确保 Web 资源是解决方案的一部分。
    • Web 资源的名称为 example_form-script.js.

步骤 4:将 Web 资源关联到窗体

  1. 在解决方案中,选择 对象>>,然后选择 编辑。

    用于在解决方案中编辑模型驱动应用的选项的屏幕截图。

  2. 展开 “帐户 ”,然后选择 “帐户”窗体。 选择...(省略号),它位于信息窗体的右侧,然后选择“编辑”。

    用于在应用中编辑帐户信息窗体的选项的屏幕截图。

  3. 在左侧导航中,选择 “窗体库 ”,然后选择“ 添加库”。

    “窗体库”窗格的屏幕截图,其中显示了“添加库”选项。

  4. 在“添加 JavaScript 库”对话框中,搜索按名称创建的 JavaScript Web 资源: Example Script

    用于选择 Web 资源的“添加 JavaScript 库”对话框的屏幕截图。

  5. 选择 示例脚本 Web 资源,然后选择 添加。

步骤 5:配置表单和字段事件

  1. 选择“ 事件 ”选项卡。

    “事件”选项卡上窗体事件处理程序的屏幕截图。

配置表单 On Load 事件

  1. 选择 “加载时 事件处理程序,然后选择 + 事件处理程序。

    配置窗体 On Load 事件处理程序的屏幕截图。

    确保以下设置正确:

    • 事件类型为“加载时”。
    • 已选择 example_example-form-script 库。
    1. 在 “函数”字段中输入函数的名称。 在本例中,输入 Example.formOnLoad。
    2. 选择“ 传递执行上下文”作为第一个参数。
    3. 选择“ 完成”。

配置表单 On Save 事件

  1. 选择 On Save 事件处理程序,然后选择 + 事件处理程序。

    配置窗体的 On Save 事件处理程序的屏幕截图。

    确保以下设置正确:

    • 事件类型为“保存时触发”。
    • 已选择 example_example-form-script 库。
    1. 在 函数 字段中键入函数的名称。 在本例中,输入 Example.formOnSave。

      注释

      无需选择 “传递执行上下文”作为此函数的第一个参数 ,因为它不使用它。

    2. 选择“ 完成”。

配置字段 On Change 事件

  1. 选择 “帐户名称 ”字段和“ 事件 ”选项卡。

    所选“帐户名称”字段的“事件”选项卡的屏幕截图。

  2. 选择“On Change”事件处理程序,然后选择“+ 事件处理程序”。

    为“帐户名称”字段配置 On Change 事件处理程序的屏幕截图。

    确保以下设置正确:

    • 事件类型为 On Change。
    • 已选择 example_example-form-script 库。
    1. 在 “函数”字段中输入函数的名称。 在此案例中,ID 为 Example.attributeOnChange。
    2. 选择“ 传递执行上下文”作为第一个参数。
    3. 选择“ 完成”。

保存和发布更改

保存 表单并选择“发布”。

步骤 6:测试代码

刷新浏览器,确保更改在模型驱动应用实例中生效。

要测试你的代码:

  1. 转到 Power Apps。

  2. 在左侧导航中,选择 “应用”。

  3. 打开刚刚编辑的模型驱动应用,或选择它并选择“ 播放”。

    打开模型驱动应用以测试客户端脚本的屏幕截图。

测试表单 On Load 函数

  1. 选择列表中的任意帐户记录将其打开。

  2. 验证是否显示通知。

    帐户窗体加载时显示的表单通知的屏幕截图。

  3. 验证通知在 5 秒内消失。

测试字段 On Change 函数

  1. 编辑帐户名称以在名称中包含“Contoso”,然后按 Tab 移动到下一列。

  2. 验证设置为 “主电话”、“ 网站”和 “说明 ”列的预期值。

    帐户名称更改时客户端脚本设置的列值的屏幕截图。

测试表单 On Save 函数

  1. 选择“保存”。

  2. 验证警报对话框是否显示代码中配置的消息。

    保存帐户窗体时显示的警报对话框的屏幕截图。

  3. 选择 “确定” 关闭警报。

后续步骤

了解如何使用浏览器开发人员工具调试客户端脚本。

调试模型驱动应用的 JavaScript 代码
模型驱动应用的表单和网格中的事件
Form OnLoad 事件
模型驱动应用中的 Form OnSave 事件(客户端 API 参考)
列 OnChange 事件(客户端 API 参考)