Power Pages客户端 API 示例

本文中的示例展示了如何结合使用 Power Pages 客户端 API,以在表单和列表中实现常见场景。 每个示例都已完成,因此你可以将其复制到 JavaScript Web 文件或页面的 “自定义 JavaScript ”部分,然后更改表单名称、列名和表名以匹配网站。

所有示例都使用 客户端 API 初始化中所述的回调模式,该模式保证客户端 API 在代码运行之前准备就绪。 该回调使用 async 声明,以便其能够使用 await。 如果您的代码未使用async,请省略await关键字。

示例 Description
根据 Dataverse 记录设置模态查找值 检索 Dataverse 记录并将其用于填充模式查找控件。
当查找呈现为下拉列表时设置查找值 根据控件呈现为下拉列表还是模态查找来设置查找值。
在多选选择列中读取和设置值 读取所选选项并添加一个选项,而无需删除现有选择。
使用服务器上只读或隐藏的控件 在更改控件行为之前检查控制可用性和只读状态。
根据另一列的值创建所需的列 根据另一个控件的值应用条件要求和自定义验证。
显示或隐藏列表中的列 隐藏新式列表列并自定义另一列的标题和工具提示。
在列表中显示或隐藏记录 隐藏非活动行并直观地区分当前用户无法编辑的记录。

从 Dataverse 记录设置模态查找值

此示例使用 Web API 检索帐户记录,并使用它在窗体上填充 模式查找 。 模式查找需要包含相关记录的 ID、名称和表名的对象。

Microsoft.PowerPages.onPagesClientApiReady(async function ($pages) {
    // 1. Retrieve the first account record.
    //    $top=1 returns a single record, and $select limits the payload to the
    //    columns that the lookup control needs.
    const queryOptions = '$select=accountid,name&$top=1';
    const response = await $pages.webAPI.retrieveMultipleRecords('accounts', queryOptions);
    const records = response.value;

    if (!records || records.length === 0) {
        console.warn('No account records were returned from Dataverse.');
        return;
    }

    const firstAccount = records[0];
    console.log(`Retrieved account: ${firstAccount.name}`);

    // 2. Get the form. Use the name or the ID of your basic or multistep form.
    const form = $pages.currentPage.forms.getFormByName('Profile Web Form (Enhanced)');

    if (!form) {
        console.error('The target form was not found on the page.');
        return;
    }

    // 3. Get the lookup control by its logical name.
    const lookupControl = form.getControlByLogicalName('new_managingpartnerid');

    if (!lookupControl) {
        console.error('The lookup control was not found on the form.');
        return;
    }

    // 4. Set the lookup value. A modal lookup expects an object that contains
    //    the id, name, and entityType values.
    lookupControl.setValue({
        id: firstAccount.accountid,
        name: firstAccount.name,
        entityType: 'account'
    });

    console.log('The lookup control is populated.');
});

Tip

若要在不知道控件逻辑名称的情况下查找控件,请枚举 form.controls 并使用 getName 方法,如 form.controls.find(control => control.getName() === 'Managing Partner') 中所示。

当查找呈现为下拉列表时设置查找值

查阅列将呈现为模式对话框或下拉列表,具体取决于窗体的配置方式。 这两个控件接受方法中的 setValue 不同值,因此请在 isDropdown 设置值之前检查属性。 下拉列表查找需要选项的 ID,模式查找需要对象。

重要

下拉列表查找仅包含其配置的视图和筛选器返回的记录。 将值设置为下拉列表中可用的记录的 ID。 在此示例中,筛选查询,以便它仅返回查找提供的记录。

Microsoft.PowerPages.onPagesClientApiReady(async function ($pages) {
    const form = $pages.currentPage.forms.getFormByName('Profile Web Form (Enhanced)');
    const lookupControl = form && form.getControlByLogicalName('new_managingpartnerid');

    if (!lookupControl) {
        console.error('The lookup control was not found on the form.');
        return;
    }

    const response = await $pages.webAPI.retrieveMultipleRecords('accounts', '$select=accountid,name&$top=1');
    const records = response.value;

    if (!records || records.length === 0) {
        return;
    }

    const account = records[0];

    if (lookupControl.isDropdown) {
        // A dropdown lookup expects the ID of the option to select.
        lookupControl.setValue(account.accountid);

        // getValue returns an object that contains the id and name of the selected option.
        const selected = lookupControl.getValue();
        console.log(`Selected option: ${selected && selected.name}`);
    } else {
        // A modal lookup expects an object.
        lookupControl.setValue({
            id: account.accountid,
            name: account.name,
            entityType: 'account'
        });
    }
});

在多选选择列中读取和设置值

多选选取列表控件存储数字数组。 本示例将选项添加到当前所选内容,而不删除某人已选择的选项。

Microsoft.PowerPages.onPagesClientApiReady(async function ($pages) {
    const form = $pages.currentPage.forms.getFormByName('Profile Web Form (Enhanced)');
    const control = form && form.getControlByLogicalName('new_areasofinterest');

    if (!control || control.getType() !== 'MultiSelectPicklist') {
        return;
    }

    // 1. Read the options that are currently selected.
    const selectedValues = control.getValue() || [];
    console.log(`Selected options: ${selectedValues.join(', ')}`);

    // 2. Add an option only when it isn't selected yet.
    //    setValue throws an error when a value isn't one of the available options.
    const newsletterOption = 740740002;

    if (!selectedValues.includes(newsletterOption)) {
        control.setValue([...selectedValues, newsletterOption]);
    }

    // 3. Clear the selection.
    // control.setValue([]);
});

处理服务器端为只读或隐藏的控件

Power Pages对服务器应用表单元数据和表权限,客户端 API 无法替代这些设置。 编写防御代码,用于检查控件是否存在,以及它是否为只读,然后再对其进行更改。

以下行为适用:

  • 不在表单上的列,或者用户没有读取权限的列,都不会显示。 getControlByLogicalName 方法会为该列返回 undefined,因此请在使用前先检查返回结果。
  • 当控件锁定在服务器上(如只读窗体或字段上的 多选选取列表 )时,该方法 setDisabled(false) 不起作用。
  • 当服务器端要求某列为必填时,setRequired(false) 方法无法将该列设为可选。
  • 该方法 setVisible(false) 仅隐藏浏览器中的控件。 使用表权限和列安全性来保护数据。 永远不要依赖隐藏控件来保护数据。
Microsoft.PowerPages.onPagesClientApiReady(async function ($pages) {
    const form = $pages.currentPage.forms.getFormByName('Profile Web Form (Enhanced)');

    if (!form) {
        return;
    }

    const creditLimit = form.getControlByLogicalName('creditlimit');

    // The column isn't on the form, or the user can't read it.
    if (!creditLimit) {
        console.log('The credit limit column is not available to this user.');
        return;
    }

    // A control that's locked on the server stays disabled, even after
    // you call setDisabled(false).
    creditLimit.setDisabled(false);

    if (creditLimit.getDisabled()) {
        console.log('The credit limit column is locked on the server.');
    }

    // Hide the control in the browser. This changes only what people see.
    // Use table permissions and column security to protect the data.
    const internalNotes = form.getControlByLogicalName('new_internalnotes');

    if (internalNotes) {
        internalNotes.setVisible(false);
    }
});

根据另一列的值创建所需的列

本示例将某一列设为仅在另一列中选择了特定选项时才必填,并添加了一个在提交表单时运行的自定义验证器。 有关详细信息,请参阅 addValidator 方法参数。

Microsoft.PowerPages.onPagesClientApiReady(async function ($pages) {
    const form = $pages.currentPage.forms.getFormByName('Profile Web Form (Enhanced)');

    if (!form) {
        return;
    }

    const contactMethod = form.getControlByLogicalName('preferredcontactmethodcode');
    const mobilePhone = form.getControlByLogicalName('mobilephone');

    if (!contactMethod || !mobilePhone) {
        return;
    }

    const applyRules = () => {
        // Option 3 is Phone in this example.
        const requiresPhone = contactMethod.getValue() === '3';

        // Make the column required and provide a localized message.
        mobilePhone.setRequired(requiresPhone, 'Enter a mobile phone number.');

        if (requiresPhone) {
            // Add a format check that runs when the form is submitted.
            // Reusing the same ID replaces the earlier validator instead of adding another one.
            mobilePhone.addValidator(
                'mobilePhoneFormat',
                (value) => /^(?=.*\d)[0-9\s+()-]{7,20}$/.test((value || '').trim()),
                'Enter a valid mobile phone number.'
            );
        } else {
            mobilePhone.removeValidator('mobilePhoneFormat');
        }
    };

    // Apply the rules when the page loads and whenever a value on the form changes.
    applyRules();
    form.getHtmlElement().addEventListener('change', applyRules);
});

注释

服务器上所需的列保持不变,即使调用 setRequired(false)。

显示或隐藏列表中的列

本示例隐藏新式列表中的列,并重命名另一列。 读取事件处理程序中的 loaded 列表数据,因为每次列表刷新、排序、筛选器或页面数据时都会再次发生该事件。 有关详细信息,请参阅 列表事件。

Microsoft.PowerPages.onPagesClientApiReady(async function ($pages) {
    const list = $pages.currentPage.lists.getListById('list_#1');

    if (!list || !list.isModern) {
        return;
    }

    list.on('loaded', () => {
        // Hide a column that people don't need to see.
        const createdOn = list.getColumn('createdon');

        if (createdOn) {
            createdOn.setVisible(false);
        }

        // Rename a column and add a tooltip that screen readers use as the
        // accessible name of the header. Read the configured display name, and
        // then derive the header so that the code produces the same result
        // each time the event occurs.
        const name = list.getColumn('name');

        if (name) {
            name.setHeader(`${name.getDisplayName()} (primary)`);
            name.setTooltip('The primary name of the account.');
        }
    });
});

在列表中显示或隐藏记录

本示例隐藏非活动记录并突出显示某人无法编辑的记录。 隐藏行只会更改列表中人员看到的内容;它不会更改服务器返回的数据或记录数。

Microsoft.PowerPages.onPagesClientApiReady(async function ($pages) {
    const list = $pages.currentPage.lists.getListById('list_#1');

    if (!list || !list.isModern) {
        return;
    }

    list.on('loaded', () => {
        list.rows.forEach((row) => {
            const state = row.getState();

            // Hide inactive records, where statecode is 1.
            if (state && state.stateCode === 1) {
                row.setVisible(false);
                return;
            }

            // Highlight the records that this user can't edit.
            const privileges = row.getPrivileges();

            if (privileges && !privileges.canWrite) {
                row.addClassName('read-only-row');

                const nameCell = row.getCell('name');

                if (nameCell) {
                    nameCell.setStyle({ fontStyle: 'italic' });
                }
            }
        });
    });
});

重要

使用 getPrivileges 方法返回的值来更改数据的显示方式。 不要使用它们来强制实施安全性。 Power Pages 在服务器端强制执行表权限。