自适应核心组件中的自定义函数Forms
本文介绍了如何使用最新的自适应表单核心组件创建自定义函数,这些组件具有最新的功能,例如:
- 自定义函数的缓存功能
- 自定义函数的全局范围对象和字段对象支持
- 支持现代JavaScript功能,如左键和箭头功能(支持ES10)
请确保在AEM Forms核心组件环境中设置最新表单版本以使用自定义函数中的最新功能。
简介
AEM Forms 6.5包括JavaScript函数,这些函数允许您使用规则编辑器定义复杂的业务规则。 虽然AEM Forms提供了多种现成的自定义函数,但许多用例需要定义您自己的自定义函数才能在多个表单中使用。 这些自定义函数允许根据特定要求处理输入的数据,从而增强表单的功能。 此外,它们允许根据预定义标准动态更改表单行为。
自定义函数的使用 uses-of-custom-function
在自适应Forms核心组件中使用自定义函数的优点包括:
- 管理数据:自定义函数管理并处理输入到表单字段中的数据。
- 正在处理数据:自定义函数可帮助处理输入到表单字段中的数据。
- 数据验证:自定义函数允许您对表单输入执行自定义检查并提供指定的错误消息。
- 动态行为:自定义函数允许您根据特定条件控制表单的动态行为。 例如,您可以显示/隐藏字段、修改字段值或动态调整表单逻辑。
- 集成:您可以使用自定义函数与外部API或服务集成。 它有助于从外部源获取数据,将数据发送到外部Rest端点,或根据外部事件执行自定义操作。
自定义函数本质上是添加到JavaScript文件中的客户端库。 创建自定义函数后,该函数即可在规则编辑器中供用户在自适应表单中选择。 自定义函数由规则编辑器中的JavaScript注释标识。
自定义函数支持的JavaScript批注 js-annotations
JavaScript注释为JavaScript代码提供元数据。 它包含以特定符号(例如,/**和@)开头的注释。 注释提供了有关代码中的函数、变量和其他元素的重要信息。 自适应表单支持自定义函数的以下JavaScript注释:
名称
Name用于标识自适应表单的规则编辑器中的自定义函数。 以下语法用于命名自定义函数:
@name [functionName] <Function Name>@function [functionName] <Function Name>@func [functionName] <Function Name>
[functionName]是函数的名称。 不允许使用空格。<Function Name> 是自适应Forms的规则编辑器中函数的显示名称。如果函数名称与函数本身的名称相同,则可以在语法中省略
[functionName]。参数
参数是自定义函数使用的参数列表。 函数可以支持多个参数。 以下语法用于定义自定义函数中的参数:
-
@param {type} name <Parameter Description> -
@argument{type} name <Parameter Description> -
@arg{type}name <Parameter Description>{type}表示参数类型。 允许的参数类型包括:- string:表示单个字符串值。
- 数字:表示单个数值。
- 布尔值:表示单个布尔值(true或false)。
- string[]:表示字符串值的数组。
- number[]:表示数值的数组。
- 布尔值[]:表示布尔值的数组。
- 日期:表示单个日期值。
- date[]:表示日期值的数组。
- array:表示包含各种类型值的泛型数组。
- 对象:表示传递到自定义函数的表单对象,而不是直接传递其值。
- 范围:表示全局对象,其中包含只读变量,如表单实例、目标字段实例以及在自定义函数中执行表单修改的方法。 此变量声明为JavaScript注释中的最后一个参数,对自适应表单的规则编辑器不可见。 scope参数可访问表单或组件的对象,以触发表单处理所需的规则或事件。 有关Globals对象及其使用方法的详细信息,单击此处
参数类型为不区分大小写,参数名称中不允许有空格。
<Parameter Description>包含有关参数用途的详细信息。 它可以有多个单词。
返回类型
返回类型指定自定义函数在执行后返回的值的类型。 以下语法用于在自定义函数中定义退货类型:
@return {type}@returns {type}{type}表示函数的返回类型。 允许的返回类型包括:- string:表示单个字符串值。
- 数字:表示单个数值。
- 布尔值:表示单个布尔值(true或false)。
- string[]:表示字符串值的数组。
- number[]:表示数值的数组。
- 布尔值[]:表示布尔值的数组。
- 日期:表示单个日期值。
- date[]:表示日期值的数组。
- array:表示包含各种类型值的泛型数组。
- 对象:表示表单对象,而不是直接表示其值。
返回类型不区分大小写。
专用
声明为私有的自定义函数不会出现在自适应表单的规则编辑器的自定义函数列表中。 默认情况下,自定义函数是公用的。 将自定义函数声明为private的语法为@private。
创建自定义函数时的准则 considerations
要在规则编辑器中列出自定义函数,您可以使用以下任意格式:
包含或不包含jsdoc注释的函数语句
您可以创建包含或不包含jsdoc注释的自定义函数。
function functionName(parameters)
{
// code to be executed
}
如果用户没有将任何JavaScript注释添加到自定义函数,则它按函数名称在规则编辑器中列出。 但是,建议包含JavaScript注释,以提高自定义函数的可读性。
带有强制JavaScript注释或注释的Arrow函数
您可以使用箭头函数语法创建自定义函数:
/**
* test function
* @name testFunction
* @param {string} a parameter description
* @param {string=} b parameter description
* @return {string}
*/
testFunction = (a, b) => {
return a + b;
};
/** */
testFunction1=(a) => (return a)
/** */
testFunction2 = a => a + 100;
如果用户没有将任何JavaScript注释添加到自定义函数,则该自定义函数不会列在自适应表单的规则编辑器中。
带有必需JavaScript注释或注释的函数表达式
要在自适应表单的规则编辑器中列出自定义函数,请以下列格式创建自定义函数:
/**
* test function
* @name testFunction
* @param {string} input1 parameter description
* @param {string=} input2 parameter description
* @return {string}
*/
testFunction = function(input1,input2)
{
// code to be executed
}
如果用户没有将任何JavaScript注释添加到自定义函数,则该自定义函数不会列在自适应表单的规则编辑器中。
创建自定义函数的先决条件
在开始将自定义函数添加到自适应Forms之前,请确保在计算机上安装了以下软件:
-
纯文本编辑器(IDE):虽然任何纯文本编辑器都可以工作,但诸如Microsoft Visual Studio Code之类的集成开发环境(IDE)可提供高级功能,以便于编辑。
-
Git:管理代码更改需要此版本控制系统。 如果未安装,请从https://git-scm.com下载。
创建自定义功能 create-custom-function
创建自定义函数的步骤包括:
使用AEM项目原型创建客户端库 create-client-library-archetype
您可以向使用AEM项目原型🔗创建的项目中添加客户端库,从而添加自定义函数。
如果您现有项目,则可以直接将自定义函数添加到本地项目。
创建原型项目或使用现有项目后,请创建客户端库。 要创建客户端库,请执行以下步骤:
添加客户端库文件夹
要将新的客户端库文件夹添加到[AEM项目目录],请执行以下步骤:
-
在编辑器中打开[AEM项目目录]。
-
找到
ui.apps。 -
添加新文件夹。 例如,添加名为
experience-league的文件夹。 -
导航到
/experience-league/文件夹并添加ClientLibraryFolder。 例如,创建一个名为customclientlibs的客户端库文件夹。位置为:
[AEM project directory]/ui.apps/src/main/content/jcr_root/apps/
将文件和文件夹添加到客户端库文件夹
将以下内容添加到添加的客户端库文件夹:
.content.xml文件js.txt文件jsfolder
Location is: [AEMaaCS project directory]/ui.apps/src/main/content/jcr_root/apps/experience-league/customclientlibs/
-
In the
.content.xmladd the following lines of code:code language-javascript <?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" jcr:primaryType="cq:ClientLibraryFolder" categories="[customfunctionscategory]"/>note note NOTE You can choose any name for client library folderandcategoriesproperty. -
In the
js.txtadd the following lines of code:code language-javascript #base=js function.js -
In the
jsfolder, add the javascript file asfunction.jswhich includes the custom functions:code language-javascript /** * Calculates Age * @name calculateAge * @param {object} field * @return {string} */ function calculateAge(field) { var dob = new Date(field); var now = new Date(); var age = now.getFullYear() - dob.getFullYear(); var monthDiff = now.getMonth() - dob.getMonth(); if (monthDiff < 0 || (monthDiff === 0 && now.getDate() < dob.getDate())) { age--; } return age; } -
Save the files.
Include the new folder in filter.xml:
-
Navigate to the
/ui.apps/src/main/content/META-INF/vault/filter.xmlfile in your [AEMaaCS project directory]. -
Open the file and add the following line at the end:
<filter root="/apps/experience-league" /> -
保存文件。
-
Build the newly created client library folder to your AEM environment by following the steps given in How to Build section.
Create and deploy custom functions through CRXDE create-add-custom-function
If you are using the latest AEM Forms and Forms add-on, you can create a custom function through CRXDE to use the latest updates of custom functions. To do so, perform the following steps:
-
Log into
http://server:port/crx/de/index.jsp#. -
在
/apps文件夹下创建一个文件夹。 For example, create a folder named asexperience-league. -
Save your changes.
-
Navigate to the created folder and create a node of type
cq:ClientLibraryFolderasclientlibs. -
Navigate to the newly created
clientlibsfolder and add theallowProxyandcategoriesproperties:
note note NOTE You can provide any name in place of customfunctionsdemo. -
Save your changes.
-
Create a folder called
jsunder theclientlibsfolder. -
Create a JavaScript file called
functions.jsunder thejsfolder. -
Create a file called
js.txtunder theclientlibsfolder. -
Save your changes.
创建的文件夹结构如下所示:
-
Double-click the
functions.jsfile to open the editor. The file comprises the code for custom function.
Let's add the following code to the JavaScript file to calculate age based on the Date of Birth(YYYY-MM-DD).code language-javascript /** * Calculates Age * @name calculateAge * @return {string} */ function calculateAge(dateOfBirthString) { var dob = new Date(dateOfBirthString); var now = new Date(); var age = now.getFullYear() - dob.getFullYear(); var monthDiff = now.getMonth() - dob.getMonth(); if (monthDiff < 0 || (monthDiff === 0 && now.getDate() < dob.getDate())) { age--; } return age; } -
保存
function.js。 -
Navigate to
js.txtand add the following code:code language-javascript #base=js functions.js -
保存
js.txt文件。
You can refer to the following custom function folder. Download and install this folder on your AEM instance.
Now, you can use the custom function in your Adaptive Form by adding the client library.
Add client library in an Adaptive Form add-client-library
Once you have deployed your client library to your AEM Forms environment, use its capabilities in your Adaptive Form. To add the client library in your Adaptive Form
-
Open your form in the edit mode. To open a form in the edit mode, select a form and select Edit.
-
打开内容浏览器,然后选择自适应表单的 指南容器 组件。
-
Click the Guide Container properties icon. 这将打开“自适应表单容器”对话框。
-
Open the Basic tab and select the name of the client library category from the drop-down list (in this case, select
customfunctionscategory).
-
单击完成。
Now, you can create a rule to use custom functions in the rule editor:
Now, let's understand how to configure and use a custom function using the Rule Editor's Invoke service in AEM Forms 6.5
Using Custom Function in an Adaptive Form use-custom-functions
In an Adaptive Form, you can use Custom Functions within the rule editor.
Let us add the following code to the JavaScript file (Function.js file) to calculate age based on the Date of Birth (YYYY-MM-DD). Create a custom function as calculateAge() which takes the date of birth as input and returns age:
/**
* Calculates Age
* @name calculateAge
* @param {object} field
* @return {string}
*/
function calculateAge(field) {
var dob = new Date(field);
var now = new Date();
var age = now.getFullYear() - dob.getFullYear();
var monthDiff = now.getMonth() - dob.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && now.getDate() < dob.getDate())) {
age--;
}
return age;
}
在上例中,当用户以(YYYY-MM-DD)格式输入出生日期时,将调用自定义函数calculateAge并返回年龄。
让我们预览表单,观察自定义函数如何通过规则编辑器实现:
在自定义函数中支持异步函数 support-of-async-functions
异步自定义函数未出现在规则编辑器列表中。 但是,可以在使用同步函数表达式创建的自定义函数中调用异步函数。
查看以下代码,了解如何使用自定义函数调用异步函数:
async function asyncFunction() {
const response = await fetch('https://petstore.swagger.io/v2/store/inventory');
const data = await response.json();
return data;
}
/**
* callAsyncFunction
* @name callAsyncFunction callAsyncFunction
*/
function callAsyncFunction() {
asyncFunction()
.then(responseData => {
console.log('Response data:', responseData);
})
.catch(error => {
console.error('Error:', error);
});
}
在上述示例中,asyncFunction函数是asynchronous function。 它通过向https://petstore.swagger.io/v2/store/inventory发出GET请求来执行异步操作。 它使用await等待响应,使用response.json()将响应正文解析为JSON,然后返回数据。 callAsyncFunction函数是一个同步自定义函数,它调用asyncFunction函数并在控制台中显示响应数据。 虽然callAsyncFunction函数是同步的,但它调用异步asyncFunction函数并使用then和catch语句处理其结果。
要查看其是否有效,让我们添加一个按钮,并为按钮创建一个规则,该规则会在单击按钮时调用异步函数。
请参考控制台窗口的插图以演示当用户单击Fetch按钮时,将调用自定义函数callAsyncFunction,进而调用异步函数asyncFunction。 检查控制台窗口以查看按钮单击时的响应:
让我们深入了解一下自定义函数的功能。
自定义函数的各种功能
您可以使用自定义函数向表单添加个性化功能。 这些函数支持各种功能,例如使用特定字段、使用全局字段或缓存。 这种灵活性允许您根据组织的要求自定义表单。
自定义函数中的字段和全局范围对象 support-field-and-global-objects
字段对象是指表单中的单个组件或元素,例如文本字段和复选框。 全局对象包含只读变量,例如表单实例、目标字段实例以及在自定义函数中修改表单的方法。
param {scope} globals必须是最后一个参数,它不会显示在自适应表单的规则编辑器中。让我们了解自定义函数如何在Contact Us表单的帮助下使用字段和全局对象,该表单使用不同的用例。
用例:使用SetProperty规则显示面板
将以下代码添加到create-custom-function部分中说明的自定义函数中,以将表单字段设置为Required。
/**
* enablePanel
* @name enablePanel
* @param {object} field1
* @param {object} field2
* @param {scope} globals
*/
function enablePanel(field1,field2, globals)
{
if(globals.functions.validate(field1).length === 0)
{
globals.functions.setProperty(field2, {visible: true});
}
}
- 您可以使用位于
[form-path]/jcr:content/guideContainer.model.json中的可用属性配置字段属性。 - 使用Globals对象的
setProperty方法对该表单进行的修改是异步的,在执行自定义函数期间不会反映这些修改。
在此示例中,personaldetails面板的验证是在单击按钮时进行的。 如果在面板中未检测到错误,则单击按钮后,另一个面板(feedback面板)将变为可见。
让我们为Next按钮创建一个规则,该规则将验证personaldetails面板,并在用户单击Next按钮时使feedback面板可见。
请参阅下图以演示单击Next按钮时验证personaldetails面板的位置。 如果personaldetails中的所有字段都已验证,feedback面板将变为可见。
如果personaldetails面板的字段中存在错误,则单击Next按钮时会在字段级别显示这些错误,并且feedback面板将保持不可见。
用例:验证字段。
按照create-custom-function部分中的说明,在自定义函数中添加以下代码以验证字段。
/**
* validateField
* @name validateField
* @param {object} field
* @param {scope} globals
*/
function validateField(field,globals)
{
globals.functions.validate(field);
}
validate()函数中传递任何参数,它将验证表单。在此示例中,自定义验证模式应用于contact字段。 用户需要输入以10开头后接8位数的电话号码。 如果用户输入的电话号码不以10开头或包含多或少8位数,则单击该按钮时将显示验证错误消息:
现在,下一步是为Next按钮创建一个规则,以验证单击按钮时的contact字段。
请参阅下图以演示,如果用户输入的电话号码不是以10开头,则在字段级别将显示错误消息:
如果用户输入有效的电话号码并且验证personaldetails面板中的所有字段,屏幕上会显示feedback面板:
用例:重置面板
按照create-custom-function部分中的说明,在自定义函数中添加以下代码以重置面板。
/**
* resetField
* @name resetField
* @param {string} input1
* @param {object} field
* @param {scope} globals
*/
function resetField(field,globals)
{
globals.functions.reset(field);
}
reset()函数中传递任何参数,它将验证表单。在此示例中,personaldetails面板在单击Clear按钮时重置。 下一步是为Clear按钮创建一个规则,该规则将在单击按钮时重置面板。
请参阅下图以显示,如果用户单击clear按钮,personaldetails面板将重置:
用例:在字段级别显示自定义消息并将字段标记为无效
您可以使用markFieldAsInvalid()函数将字段定义为无效,并在字段级别设置自定义错误消息。 fieldIdentifier值可以是fieldId、field qualifiedName或field dataRef。 名为option的对象的值可以是{useId: true}、{useQualifiedName: true}或{useDataRef: true}。
用于将字段标记为无效并设置自定义消息的语法包括:
globals.functions.markFieldAsInvalid(field.$id,"[custom message]",{useId: true});globals.functions.markFieldAsInvalid(field.$qualifiedName, "[custom message]", {useQualifiedName: true});globals.functions.markFieldAsInvalid(field.$dataRef, "[custom message]", {useDataRef: true});
按照create-custom-function部分中的说明,在自定义函数中添加以下代码,以在字段级别启用自定义消息。
/**
* customMessage
* @name customMessage
* @param {object} field
* @param {scope} globals
*/
function customMessage(field, globals) {
const minLength = 15;
const comments = field.$value.trim();
if (comments.length < minLength) {
globals.functions.markFieldAsInvalid(field.$id, "Comments must be at least 15 characters long.", { useId: true });
}
}
在此示例中,如果用户在“注释”文本框中输入的字符数少于15个,则会在字段级别显示自定义消息。
下一步是为comments字段创建规则:
请参阅下面的演示,说明在comments字段中输入负反馈会触发字段级别的自定义消息显示:
如果用户在“评论”文本框中输入的字符超过15个,则验证该字段并提交表单:
用例:将更改的数据提交到服务器
以下代码行:globals.functions.submitForm(globals.functions.exportData(), false);用于在操作后提交表单数据。
- 第一个参数是要提交的数据。
- 第二个参数表示在提交之前是否验证表单。 它是
optional,默认设置为true。 - 第三个参数是提交的
contentType,该参数也是可选的,默认值是multipart/form-data。 其他值可以是application/json和application/x-www-form-urlencoded。
按照create-custom-function部分中的说明,在自定义函数中添加以下代码,以在服务器上提交操作数据:
/**
* submitData
* @name submitData
* @param {object} field
* @param {scope} globals
*/
function submitData(globals)
{
var data = globals.functions.exportData();
if(!data.comments) {
data.comments = 'NA';
}
console.log('After update:{}',data);
globals.functions.submitForm(data, false);
}
在此示例中,如果用户将comments文本框留空,则NA在提交表单时提交给服务器。
现在,为提交数据的Submit按钮创建规则:
请参阅以下console window的图示,以演示如果用户将comments文本框留空,则在服务器上提交值为NA:
您还可以检查控制台窗口以查看提交到服务器的数据:
对自定义函数的缓存支持
自适应Forms在规则编辑器中检索自定义函数列表时,为自定义函数实施缓存以增强响应时间。 error.log文件中显示一条消息,名称为Fetched following custom functions list from cache。
支持缓存的
如果修改了自定义函数,缓存将失效,并且会进行解析。
疑难解答 troubleshooting
-
用户需要确保核心组件和规范版本设置为最新版本。 但是,对于现有AEM项目和表单,还需要执行其他步骤:
-
对于AEM项目,用户应使用
submitForm()替换submitForm('custom:submitSuccess', 'custom:submitError')的所有实例并部署该项目。 -
对于现有表单,如果自定义提交处理程序无法正常运行,用户需要使用规则编辑器在 提交 按钮上打开并保存
submitForm规则。 此操作将submitForm('custom:submitSuccess', 'custom:submitError')中的现有规则替换为表单中的submitForm()。
-
-
如果包含自定义函数代码的JavaScript文件出错,则自定义函数不会列在自适应表单的规则编辑器中。 要检查自定义函数列表,您可以导航到
error.log文件以查找错误。 如果出现错误,自定义函数列表显示为空:
如果没有错误,则会获取自定义函数并显示在
error.log文件中。error.log文件中显示一条消息,名称为Fetched following custom functions list:使用正确的自定义函数
注意事项
-
parameter type和return type不支持None。 -
自定义函数列表中不支持的函数包括:
- 生成器函数
- 异步/等待函数
- 方法定义
- 类方法
- 默认参数
- Rest参数