# 动态脚本

动态脚本和前面所述的动态公式动态样式动态动作动态验证相比具有更大的灵活性,在动态脚本里允许以javascript语法自定义函数并执行,所以可以实现很多其他四种动态所不能实现的效果。


动态脚本的第一个栏位填的是自定义脚本,第二个栏位填写的是所有能触发这段脚本的字段列表,多个字段之间以逗号分隔。动态脚本会在第二个栏位上填写的任何一个字段变化时执行(详见触发字段列表),也会在控件创建时执行。控件创建有两个时机:1.表单初始化 2.重复节表新增行创建了这个控件。如果第二个栏位不填任何内容表示此动态脚本只在控件创建时执行一次,当然也包括表单初始化时和重复节表新增行时。

# 重要概念

重要概念

  • 可以将第一个栏位填写的脚本视为回调函数,在这个回调中执行副作用;
  • 可以将第二个栏位填写的触发字段列表视为侦听的数据源,一旦源发生变动,副作用即刻执行;
  • 这个副作用函数会在表单初始化时先执行一次。

# 执行上下文

在动态脚本的执行上下文中封装了所有字段的值(及属性)、字段(包括重复节表)对象引用、this对象引用内置变量内置函数,以上这些都可以在动态脚本中使用。此外用户也可以自定义局部或者全局的函数在动态脚本中使用。
关于字段值和字段对象引用的概念请参见表单引用

# 对象引用

对象引用分字段对象重复节表对象视图对象根对象四种,每种对象的封装请点各自链接。在动态脚本中这四个类型的对象引用都可使用,另外还可以通过this来引用定义动态脚本的控件自身,以下通过示例来说明各种引用对象的用法。

# this引用自身对象

在字段、重复节表、或者根对象上设置的动态脚本中都可以通过this来引用自身。

示例 字段的动态脚本中的this
// 设置本字段值为'a'
this.val('a');
1
2
示例 重复节表的动态脚本中的this
// 将第一行设置为不可见
this.itemVisible(false,0);
1
2
示例 根对象的动态脚本中的this
// 将审核这个视图设置为不可见
this.getView['审核'].visible(false);
1
2

# 引用其它控件字段对象

# 引用其它字段对象

对于其他字段对象的引用和其他动态一致,建议使用$fieldXXX.control的形式。

示例 动态脚本中使用其他字段对象引用
// 根据重复表中的fieldAmount字段加总值设置fieldTotal的值;如果这个动态直接设置在fieldTotal上的话可直接使用this.val(sum($fieldAmount))
$fieldTotal.control.val(sum($fieldAmount));
1
2

# 引用其它重复节表对象

动态脚本中可以使用其他重复节表对象引用,直接用$groupXXX即可。

示例 动态脚本中使用其他重复节表对象引用
// 根据字段fieldShowMember控制是否显示groupMember;如果这个动态直接设置在groupMember上的话可以直接使用this.visible($fieldShowMembers)
$groupMember.visible($fieldShowMembers)
1
2

# 引用视图对象

所有动态脚本中都可通过$VIEWS['视图名']来引用视图对象,根对象的动态脚本中还可以通过this.views['视图名']或者this.getView('视图名')来引用视图对象。

示例 动态脚本中使用$VIEWS来引用视图对象
// 将审核这个视图设置为不可见
$VIEWS['审核'].visible(false);
1
2

# 引用根对象

所有动态脚本中都可通过$GLOBAL来引用根对象。

示例 动态脚本中使用$GLOBAL来引用根对象

// 通过根对象将审核这个视图设置为不可见
$GLOBAL.views['审核'].visible(false);
1
2

# 对象引用封装

不同类型的对象引用上封装了不同的属性和方法,详见引用对象章节。以下对字段对象方法的封装再次进行说明。

# 通用方法(每个控件对象上都有)

使用this或者$fieldXXX.control的形式可以分别引用字段本身或者其他字段对象,利用字段对象上封装的方法实现逻辑。字段对象上所有的方法请参考表单引用部分关于字段对象方法封装的文档。我们可以注意到字段对象上封装的方法对动态公式、动态样式、动态动作、动态验证功能进行了覆盖,这也就意味着可以只在字段上配置动态脚本替代其他四种动态,具体可以用引用对象上什么方法分别替代另四种动态请参考以下相关章节

# 控件方法(不同控件类型独有)

封装的方法包括上述的所有控件都有的通用方法以及每种控件上独有的方法,这些独有的方法被称之为控件暴露的方法(exposed functions),暴露的含义是这些方法和控件上多数方法不同,不但控件内部代码可以使用,同时通过控件对象引用开发者也可以使用这些方法实现一些功能。

这些独有的方法可以参考每种控件的文档,也可以在表单引用章节参见控件方法列表

示例 使用控件暴露的方法
// 以下调用checklist控件的全选功能
this.checkAll();
1
2

# 可用的变量和函数

在动态脚本执行上下文中有很多可用的变量和函数,描述如下:

# 内置变量和内置函数

在动态脚本中可以使用所有预定义的内置变量以及所有的内置函数(部分内置函数不适合动态脚本中使用,具体可参考各内置函数说明)。

# 自定义函数

开发者可以在动态脚本中根据自己的需求自定义函数,请注意该函数仅在自己这段脚本中生效。

# 自定义全局函数

开发者可以在表单根对象上定义全局函数,这个函数可以在任意动态脚本中使用。由于定义全局函数只需要在表单初始化时候执行一次,所以触发字段列表栏位可以不填。使用根对象上的defineGlobalFunction方法即可定义全局函数

// 以下在表单根对象上定义一个全局函数plus,在其它动态脚本中可通过plus(var1,var2)来调用,触发字段列表可不填
this.defineGlobalFunction('plus',function(a,b){
  return a+b;
});

// 在任意字段动态脚本上可使用的plus函数,以下会设置字段值为fieldA和fieldB之和,触发字段列表可填$fieldA,$fieldB
this.val(plus($fieldA,$fieldB));
1
2
3
4
5
6
7

# 自定义全局变量

开发者可以在表单根对象上定义全局变量,这些全局变量可用于参与动态计算,在不同的动态之间记录一些全局状态,用作动态的触发字段或者触发条件,省却在表单上定义一些不显示的隐藏控件。使用根对象上的defineGlobalVariable即可自定义全局变量。

注意事项
  • 建议在根对象的全局初始化脚本中使用,确保其他动态脚本中调用这个全局变量时该变量已完成定义。在其他字段脚本中使用请自行确保其能先定义、后使用。
  • 变量名的命名规则为以大小写字母_$开头,后续字符也可以使用数字,最大255个字符。
  • 全局变量值的类型只限于string,number,boolean,null,undefined五种,不支持对象类型。
  • 定义的全局变量会随表单的保存或提交流转于各步骤,事实上用户自定义的变量会以json格式保存于表单内置变量_VAR_GLOBAL_VARIABLES里。
  • 在脚本中可使用$VARIABLES[name]来引用名称name指定的自定义全局变量,也可以用$VARIABLES作为动态脚本的触发字段。
  • 对全局变量赋值直接使用$VARIABLES[name] = newValue即可。
示例 定义全局变量示例
// 定义在表单根对象的scripts里
this.defineGlobalVariable("sum",0);
this.defineGlobalVariable("status","starting");
this.defineGlobalVariable("visible",false);
1
2
3
4
示例 全局变量赋值与触发动态
// 以下可定义在fieldApprover的scripts上
if ($fieldApprover != "") {
    $VARIABLES["status"] = "approving";
}

// 以下可定义在groupInfo的scripts上,触发字段列表为$VARIABLES
if ($VARIABLES["status"] === "approving") {
    this.visible(true);
}
1
2
3
4
5
6
7
8
9

# 触发字段列表

动态的触发由第二个栏位填写的触发字段列表变化引起,表单侦听这些字段的改变,改变发生即刻执行由第一个栏位定义的回调函数,这个回调函数也可视作副作用函数,这也正是本文档最开始重要概念所述。如果该动态脚本会由多个字段触发,那么触发字段列表中将这些字段之间用英文逗号符分隔即可。
表单初始化时所有字段的动态脚本会执行一次,如果触发字段列表不填,那么表单上已经存在的字段初始化执行脚本后这段脚本将不会再有机会触发。

触发字段列表填写的内容会有字段、重复节表、全局变量三种情况:

# 字段变化触发

当表单上字段内容由于用户填表或者FieldChange事件回传值发生变化时,就会触发相关的动态。字段如果是Code类型,其代码值发生改变才会触发动态,如果是显示值发生变化而代码值不变是不会触发动态的。要想由字段变化触发脚本,触发列表中填入$fieldXXX即可。

# 重复节表变化触发

当重复节表发生了新增、删除、上下移动行、重复表点击了表头排序这些情况时我们认为重复节表发生了变化,就会触发这个重复节表相关的动态(触发列表中填写$groupXXX)。重复节表行内的控件值发生变化不被认为是重复节表的变化,如果想在行内控件发生变化时触发动态,请直接将这个字段放到触发列表中,而不是重复节表自身。要想由重复节表变化触发脚本,触发列表中填入$groupXXX即可。关于重复节表触发动态的详细描述可参考此处

# 全局变量变化触发

将$VARIABLES放到触发列表中可用于全局变量变化时触发动态,全局变量可用于替代表单上过多的隐藏控制字段,请善加利用。要想由全局变量变化触发脚本,触发列表中填入$VARIABLES即可。

# 全局初始化脚本

定义在根对象上的动态脚本,如果没有设置触发字段列表,那么这段脚本只会在表单初始化时执行一次,而且由于其设置在根对象上,所以会在所有动态中最先执行。这种设置在根对象上且只在表单初始化时执行一次的动态脚本被称为全局初始化脚本。一般自定义全局函数,自定义全局变量,注册操作脚本以及设置表单字段初始值的工作都会放到全局初始化脚本中做。

# 比较

传统的动态包括动态公式、动态样式、动态动作、动态验证四种,动态脚本是较晚开发出来的动态功能,意图对前面几种动态功能上进行全覆盖,在触发时机上以及动态配置上略有不同,以下说明。

# 触发时机

触发时机\动态 动态公式 动态样式 动态动作 动态验证 动态脚本
字段变化(注) Y(注) Y Y Y Y
表单初始化 N Y Y N Y
重复节表变动 Y Y Y Y Y
表单提交 N N N Y N
控件失去焦点 N N N Y N
FieldChange Y(注) Y Y Y Y
自定义全局变量变化 Y Y Y Y Y

备注

  • 字段变化触发动态因控件而异,单行和多行文本框内容由用户输入而改变后需要失去焦点才会触发动态,Select、Suggester、Option、Check等控件用户点选后即刻触发动态
  • 表单初始化时动态公式是不执行的,除非这个控件在重复节表中因为MinOccur设置了值而新增出来的行里,这种情况下动态公式才会在表单初始化时候执行
  • FieldChange改变表单字段数据后会触发所有动态,但是如果FieldChange事件中有返回值,那么就会忽略触发动态公式后的计算值,采用事件中传回的数据作为表单字段数据,即FieldChange传回的值优先于动态公式计算值

# 配置比较

动态脚本和其他动态比较,其配置项也是两项,第一配置项是动态脚本的内容,第二配置项是监听字段列表(触发条件)。
从配置的第一项内容看,动态脚本的内容是一段javascript代码,而其他几种动态仅仅是一个表达式(该表达式的语法是javascript语法的表达式的一个子集)

配置\动态 动态公式 动态样式 动态动作 动态验证 动态脚本
第一配置项 表达式(公式值) 表达式(样式字符串) 表达式(动作参数) 表达式(验证提示字符串) js语法脚本
第二配置项 表达式(执行条件) 表达式(执行条件) 表达式(执行条件) 表达式(执行条件) 字段列表,逗号分隔(监听数据列表)

# 变量函数支持

变量与函数\动态 动态公式 动态样式 动态动作 动态验证 动态脚本
内置变量 支持 支持 支持 支持 支持
内置函数 支持 支持 支持 支持 支持
自定义变量、函数 不支持 不支持 不支持 不支持 支持

# 对象引用支持

变量与函数\动态 动态公式 动态样式 动态动作 动态验证 动态脚本
其它对象引用 支持 支持 支持 支持 支持
this对象引用 不支持 不支持 不支持 不支持 支持

# 替代其它动态

动态脚本可以替代其它所有动态功能,以下列出了所有替代方案

控件对象 其他动态功能 动态脚本替代
普通控件 动态公式value val
普通控件 动态样式style cssstyle
普通控件 动态样式rowStyle rowStyle
普通控件 动态样式cellStyle cellStyle
重复控件 动态样式style style
重复控件 动态样式rowStyle rowStyle
重复控件 动态样式cellStyle cellStyle
普通控件 动态动作visible visible
普通控件 动态动作rowVisible rowVisible
普通控件 动态动作colVisible colVisible
普通控件 动态动作tableVisible tableVisible
重复控件 动态动作visible visible
重复控件 动态动作rowVisible rowVisible
重复控件 动态动作colVisible colVisible
重复控件 动态动作tableVisible tableVisible
普通控件 动态动作readOnly readOnly
重复控件 动态样式itemStyle itemStyle
重复控件 动态动作itemVisible itemVisible
重复控件 动态动作itemReadOnly itemReadOnly
普通控件 动态动作dataSource dataSource
普通控件 动态动作tooltip tooltip
普通控件 动态动作notNullMark setNotNullMark
视图 动态动作visible visible
视图 动态动作titleVisible titleVisible
普通控件 动态验证validate registerValidation

# 示例


如图所示,这里在fieldScript31字段上定义了动态脚本。触发的字段列表为$fieldSource3,$fieldCheck1,这意味着这两个字段中任意一个的值变化都能使这段脚本执行。脚本内容意思是如果fieldCheck1字段为true,那么fieldScript31字段的值将跟随fieldSource3字段的值进行变化,变化内容就是fieldSource3值本身。

另外我们可以注意到字段控件类型后面跟着两种图标,出现绿色图标表示这个字段上定义了动态(动态公式、样式、动作、验证、脚本中任意一种);出现蓝色箭头图标说明这个字段是其他字段侦听的数据源,这个字段发生变化时会触发其他字段的动态脚本执行,将鼠标停在蓝色图标上会显示哪些字段会因其触发动态脚本。

# 常见问题

# 动态脚本使用什么语法

动态脚本支持es5、es6语法,不过鉴于浏览器的兼容性请使用es5语法。当未来浏览器兼容性不是问题时可抛弃es5语法,非常遗憾目前还只能使用es5。

# 仅初始化执行和跳过初始化执行

动态脚本会在表单初始化时先执行一次,如果您想让脚本仅在初始化时候执行,那么可以将条件配置设置为空,即没有其他字段变化会引起脚本再次执行。如果您想让脚本在初始化时候不执行,那么请在脚本中使用内置变量进行判断。

if (!$INIT) {
    // do something
}
1
2
3

# 非空判断

对于重复节表中的字段,如果在脚本中引用了,当重复节表没有数据时,请注意进行非空判断,不判断会引起脚本异常。

if ($fieldRepeatEdit !== undefined) {
    // do something
}
1
2
3

# 是否支持全局变量

请注意动态脚本中并不支持使用window,document这样的全局变量。

# 是否支持操作控件的DOM

为了表单页面能正常工作,不支持直接操作控件的DOM。

# 是否可以用脚本设置字段初值

可以通过调用val方法时传递force为true选项设置初值,但请充分考虑用脚本赋初值而不是在字段上设置InitialValue的必要性。使用val方法赋初值将会忽略表单上已经存在的值(用户提交或者保存的值),通常这将引发错误,除非是特殊情况下才有可能正确。另外如果设置值的字段还被其他动态依赖,为了表单初始化时其他动态能正常的执行,请在全局初始化脚本中设置初值,这将保证在其他动态执行前初值已经正确的设置。

# 是否可以只使用动态脚本完成所有动态功能

是的,动态脚本的功能覆盖了动态公式、动态样式、动态动作、动态验证所有的功能,您完全可以只使用动态脚本来实现所有需要的动态功能。