本地表达式

在浏览器沙箱中运行的 JavaScript

  1. 命名规范
  2. 计算
  3. 转换
  4. 把对象数组转换为 HTML 表格
  5. 获取带递增编号的名称
  6. 对象数组处理
  7. 用原生 JavaScript 处理对象数组

以下示例使用字段属性 runLocal: true 运行。
它们在浏览器沙箱中执行,可以使用完整的 JavaScript 引擎。

提示:类型 local 可作为 type: expression, runLocal: true, hide: true, output: false 的别名
提示:类型 local_out 可作为 type: expression, runLocal: true, hide: true 的别名


命名规范

用字符串操作来套用命名规范。

'$(field1) $(field2)'.replace('-','_').toUpperCase()

计算

用数学运算进行计算。

Math.round($(field1)*$(field2)*Math.PI)   // Math.round and Math.PI are native javascript

转换

把字节转换为 GB。

($(size_bytes)/1024/1024/1024).toFixed(2)  // toFixed is native javascript method

把对象数组转换为 HTML 表格

把对象数组(例如来自另一个字段)转换成 HTML 表格,供 html 字段使用:

fnToTable($(my_array_field),{
  tableClass: '',
  escapeHtml: true,
  emptyCell: '',
  includeHeader: true
})

// output : an html-table representation of the array of objects taken from another field called "my_array_field"
// tip : add tableClass: 'table table-striped table-bordered' for bootstrap styling

获取带递增编号的名称

使用自动编号时,您可能需要在一组带编号的字符串中找出下一个名称。
此函数也可作为服务器端表达式使用(加前缀 fn. )。

fnGetNumberedName(['server001','server002','server005'],'server###','server001',false)
// result : "server006"

fnGetNumberedName(['server001','server002','server005'],'server###','server001',true)
// result : "server003"

fnGetNumberedName($(fieldlist),'server###','server001',true)
// use another expression field as input for the array

// fnGetNumberedName(array,pattern,default,fillgaps)
// This function searches for a numbered pattern in a list of string, 
// increases the highest number and returns a name like the pattern
// - array : an array object, you can use a placeholder to an expression where you know it's an array
// - pattern : a string that hold the # as a digit
// - default : if no value is found, return this default
// - fillgaps : a boolean to indicate it can fill gaps in the numbers, 1,2,3,6 => 4

当第一个参数不是数组时,本地函数返回默认值。而服务器函数 fn.fnGetNumberedName 则会报错失败。


对象数组处理

对象数组经常需要筛选、修改和排序。
AnsibleForms 提供了一个自定义辅助工具,让这类代码保持简洁。

/* 
  fnArray.from($(your_array_field))                               // custom helper library
      .filterBy({property1:'value1',property2:'value2', ...})     // filters by property value (a string, * wildcards allowed)
      .regexBy({property1:'regex1',property2:'regex2', ...})      // filters the array by property matched against regex
      .distinctBy('property1','property2', ...)                   // will make the array entries unique by property
      .selectAttr({prop1:'property1',prop2:'property2'})          // only selects a certain property, and you can relabel them
      .sortBy('property1','-property2', ...)                      // will order the array.  To have descending add a "-" (minus) before the property

  mylist:
  [
    {
      name:'Spiderman',
      has_ability: true,
      ability: 'Can do whatever a spider can'
    },
    {
      name:'Superman',
      has_ability: true,
      ability: 'Superstrong,Flying,Laserbeams'
    },     
    {
      name:'FamilyGuy',
      has_ability: false
    },    
    {
      name:'Wolverine',
      has_ability: true,
      ability: 'Enhanced healing'
    }                                                  
  ]
*/

fnArray.from($(mylist))         // take data from another field 'mylist'
.regexBy({name:'.*man$'})       // name must end with 'man'
.filterBy({has_ability:'true'}) // must have abilities (a string: 'true', not true)
.selectAttr({name:'name',ability:'ability'})   // only take properties name and ability
.sortBy('-name')                // sort by name descending

/*
  result : 
  [
    {name:'Superman',ability:'Superstrong,Flying,Laserbeams'},
    {name:'Spiderman',ability:'Can do whatever a spider can'}
  ]
*/

用原生 JavaScript 处理对象数组

所有标准 JavaScript 数组方法仍然可用于筛选和修改数据,例如 map 、 forEach 、 find 、 filter 和 reduce 。

// source : https://medium.com/@jeff_long/understanding-foreach-map-filter-and-find-in-javascript-f91da93b9f2c

mylist=
  [
    {
      name:'Bob',
      age: 5
    },
    {
      name:'Tom',
      age: 10
    },     
    {
      name:'Paul',
      age: 30
    },    
    {
      name:'Tom',
      age: 40
    }                                                  
  ]

// simple filter
$(mylist).filter((x) => x.age<=20) // filter age<=20
/* result:
[
  {name:'Bob',age:5},
  {name:'Tom',age:10}
]
*/

// filter and addition
$(mylist)
  .filter((x) => x.age<=20)   // filter age<=20
  .map((x) => { return {...x,diff:20-x.age} }) // add new property diff
/* result:
[
  {name:'Bob',age:5,diff:15},
  {name:'Tom',age:10,diff:10}
] 
*/

// find
$(mylist).find((x) => x.name=='Tom').age  // find age of first Tom
// result: 10

// make sum with reduce
$(mylist).reduce((sum,x) => sum+x.age,0) // calculate sum of ages
// result: 85

// make temp function
((arr,min)=>{
  return arr
    .filter(x => x.age>=min)  // filter
    .map(x => {
      var preview=`${x.name} (${x.age})`; // make preview string
      return {...x,preview:preview} })    // add new preview property
})($(mylist),20)                          // feed function with mylist and 20       
/* result:
[
  {name:'Paul',age:30,preview:'Paul (30)'},
  {name:'Tom',age:40,preview:'Tom (40)'}
] 
*/