Metadata-Driven Variable Assignment

This action is used to assign values to a set of variables using metadata.

Metadata-driven variable assignment lets you use metadata to specify how assignment should be performed.

This form takes a map of target expression and assignment metadata pairs. For example, if the target expression is a structure, it has to resolve to a variable or to a variable's property. The target expression has to be prefixed with one of the following:

  • $application.variables
  • $page.variables
  • $chain.variables
  • $variables

This should be followed by a variable name or a path to a variable property, such as the following:

  • $application.variables.a
  • $page.variables.a.b
  • $variables.a.b.c

Note that $variables.a.b.c is a shortened form of $chain.variables.a.b.c.

The expression can be arbitrarily complex as long as it is a valid JavaScript expression and satisfies the above constraints.

The assignment metadata has the following format:

{
  "source": "some expression",
  "reset": "none", // default to " toDefault"
  "auto": "always", // default to "ifNoMappings"
  "mapping": { ... }
}

The "source" expression can be an arbitrary expression that evaluates to a primitive value, an object or an array.

The "reset" option can be one of the following:

  • "toDefault" - reset the target to its default value before assignment. This is the default.

  • "empty" - clear the target before assignment. If the target has an object type, the target will be reset to an empty object of that type. If the target is an array, the target will be reset to an empty array.

  • "none" - overwrite the existing target value

The "auto" option controls whether to auto-assign all properties from the source to the corresponding properties of the target. It can be set to one of the following:

  • "always" - auto-assignment will always be performed first before any mapping is applied.

  • "ifNoMapping": auto-assignment will only be performed if no mapping is provided. This is the default.

The "mapping" is a piece of metadata used to provide fine-grained control over what gets assigned from the source to the target. When no "mapping" is used to control the assignment, there are two possible schemes for assignment depending on the target type, auto and direct.

Auto Assign Source to Target 

If the target has a concrete type, the assign action will auto-assign the source to the target. If the target type is an object type, auto-assignment will recursively assign each property in the source object to the corresponding property in the target object based on the target type. If the target is an array, the source will be treated as an array if it is not one already. For each item of the source array, an empty item will be created using the target's array item type and appended to the target array. The source item is then auto-assigned to the target item. 

If the target property is an object and the source property is a primitive or vice versa, no assignment will be made. For primitive types, the source value will be coerced into the target type before assignment. For boolean type, the coercion will be based on whether the source value is truthy except for "false" (case-insensitive) and "0" which will be coerced to false.

Direct Assign Source to Target 

If the target has a wildcard type, e.g., any, any[], object or object[], direct assignment will be performed. The behavior may differ depending on the wildcard type:

  • any - the source value is directly assigned to the target

  • any[] - the source value is turned into an array if not one already and then directly assigned to the target

  • object - same as any except the source value has to be an object. Otherwise, no assignment is performed.

  • object[] - same as any[] except the items in the source array have to be objects. Otherwise, no assignment is performed.

Example: Metadata-driven assignment takes a map of target expression and assignment metadata pairs.

"myActionChain": {
  "root": "myAssignVariableAction",
  "actions": {
    "myAssignVariableAction": {
      "module": "vb/action/builtin/assignVariablesAction",
      "parameters: {
        "$page.variables.target1": { "source": "{{ $page.variables.source1 }}" },
        "$page.variables.target2": { "source": "{{ $page.variables.source2 }}" }
      }
    }
  }
}
Example: Mapping metadata is used to assign specific properties from source to target:
"$page.variables.target": {
  "source": "{{ $page.variables.source }}",
  "mapping": {
    "$target.a": "$source.b",
    "$target.b.c": "$source.c.b"
  }
} 
Example: Mapping can also be nested:
"$page.variables.target": {
  "source": "{{ $page.variables.source }}",
  "mapping": {
    "$target.a": "$source.b",
    "$target.b": {
      "source": "$source.c"
      "mapping": {
        "$target.c": "$source.b"
      }
    }
  }
}