Widgets/Transformer

Template String Widget

Template String Widget

A "Transformer" type widget. Template String Widget allows you to create dynamic strings by replacing placeholders (using JavaScript expression syntax with {{expression}}) in a template with values from an input object, pre-defined date/time variables, and global variables.

 

Inputs

  • input (DataType: Anything) This port accepts any data type. The data received will be available in the template under the input variable. If the input is a primitive type (e.g., string, number, boolean), it will be wrapped in an object like { value: your_input }.

Outputs

  • text (DataType: String) This port outputs the processed string with all placeholders replaced by their corresponding values.

Custom Settings

The Template String Widget has a text area where you define the template string. You can use JavaScript expression syntax (e.g., {{input.value}}, {{date.year}}, {{$vars.myVariable}}) to insert dynamic content. For complex operations, use the $fn() helper to execute JavaScript code (e.g., {{$fn("input.map(item => item.name).join(', ')")}}).

It also includes a "Format" drop down list with the following options:

  • Text — Trims the template string (default)
  • JSON — Formats the template string as a JSON. If the content is not valid JSON, it remains unchanged
  • HTML — Formats the template string as HTML

Important Note: The format options only improve the editing experience and don't change the final output when the template is actually rendered. The output will be exactly as you write it in the template editor — HTML won't be rendered automatically, and JSON won't be converted to objects.


Template String Settings



Available Template Variables

When crafting your template, you have access to the following variables and helpers:

input

This object contains the data passed to the input port.

  • If the input is an object, you can access its properties directly (e.g., {{input.propertyName}})
  • If the input is a primitive type (e.g., a string "Hello"), it will be available as {{input.value}}
  • Bracket notation: Use bracket notation to access properties with special characters or spaces:
    • {{input['key with spaces']}} - Access properties with spaces using single quotes
    • {{input["key with spaces"]}} - Access properties with spaces using double quotes
    • {{input[0]}} - Access array elements by numeric index

date

This object provides various date and time properties:

  • year: Full year (e.g., 2025)
  • month: Month of the year (1-12)
  • day: Day of the month (1-31)
  • hours: Hour of the day (0-23)
  • minutes: Minutes of the hour (0-59)
  • seconds: Seconds of the minute (0-59)
  • milliseconds: Milliseconds of the second (0-999)
  • time: Milliseconds since epoch
  • dayOfWeek: Day of the week (0 for Sunday, 1 for Monday, etc.)
  • dayName: Full name of the day (e.g., "Monday")
  • shortDayName: Short name of the day (e.g., "Mon")
  • date: Alias for day
  • fullYear: Alias for year
  • timezoneOffset: Timezone offset in minutes
  • UTCDate: Day of the month in UTC (1-31)
  • UTCDay: Day of the week in UTC (0 for Sunday, 1 for Monday, etc.)
  • UTCFullYear: Full year in UTC
  • UTCHours: Hour of the day in UTC (0-23)
  • UTCMilliseconds: Milliseconds of the second in UTC (0-999)
  • UTCMonth: Month of the year in UTC (1-12)
  • UTCMinutes: Minutes of the hour in UTC (0-59)
  • UTCSeconds: Seconds of the minute in UTC (0-59)
  • isoString: ISO 8601 string representation of the date (e.g., "2025-05-24T10:30:00.000Z")
  • localeString: Locale-specific string representation of the date

$vars

This object provides access to global variables defined in your workspace:

  • Dot notation: {{$vars.variableName}} - Access a global variable by name
  • Bracket notation (static): {{$vars["variableName"]}} - Access using string literal
  • Bracket notation (dynamic): {{$vars[input.fieldName]}} - Access using dynamic key from context
  • Returns the current value of the global variable
  • Returns undefined if the variable doesn't exist
  • Note: Nested bracket notation like $vars[$vars["key"]] is not currently supported

$secrets

This object provides access to secrets mapped to the recipe:

  • Dot notation: {{$secrets.secretName}} - Access a secret by name
  • Example: {{$secrets.apiKey}} retrieves the secret named "apiKey"
  • Returns the decrypted secret value if it exists and is mapped to the recipe
  • Returns an empty string if the secret doesn't exist or is not mapped
  • Security note: Bracket notation ($secrets["key"]) is not currently supported

$fn() Helper

This helper allows you to execute JavaScript code within your template for complex operations:

  • Syntax: {{$fn("javascript_code_here")}}
  • Array operations: {{$fn("input.map(item => item.name).join(', ')")}}
  • Filtering: {{$fn("input.filter(item => item.active).length")}}
  • Calculations: {{$fn("input.reduce((sum, item) => sum + item.price, 0)")}}
  • Conditionals: {{$fn("input.length > 0 ? 'Items available' : 'No items'")}}
  • String methods: {{$fn("input.name.toUpperCase()")}}
  • Complex Math: {{$fn("Math.sin(PI / 4)")}}
  • All variables from your template context (input, date, $vars) are available within $fn()

Math Functions (Available Directly)

These Math functions can be used directly in expressions without $fn():

  • Basic: round(), floor(), ceil(), abs()
  • Min/Max: min(), max()
  • Powers: sqrt(), pow()
  • Constants: PI, E
  • Example: {{round(input.price)}}, {{max(a, b, c)}}, {{PI * radius * radius}}

Array Operations

When working with arrays in your templates, use the $fn() helper with JavaScript array methods for powerful data manipulation:


Basic Array Access

  • Direct indexing: {{input[0]}} for the first element
  • Array length: {{input.length}} for the total number of elements (only when input is directly an array; for nested arrays like input.tasks.length, use {{$fn("input.tasks.length")}})
  • Property access: {{input[0].name}} for object properties within arrays

Array Iteration with $fn()

  • Simple mapping: {{$fn("input.map(item => item.name).join(', ')")}}
  • With indexing: {{$fn("input.map((item, index) => (index + 1) + '. ' + item).join('\\n')")}}
  • Conditional formatting: {{$fn("input.map((item, index) => (index === 0 ? '[FIRST] ' : '') + item).join(', ')")}}
  • First/last detection: {{$fn("input.map((item, index, arr) => item + (index === arr.length - 1 ? ' [LAST]' : '')).join(', ')")}}

Advanced Array Operations

  • Filtering: {{$fn("input.filter(item => item.active).map(item => item.name).join(', ')")}}
  • Sorting: {{$fn("input.sort((a, b) => a.name.localeCompare(b.name)).map(item => item.name).join(', ')")}}
  • Calculations: {{$fn("input.reduce((sum, item) => sum + item.price, 0)")}}

 

Examples

Basic Usage with Date Variables

This example demonstrates how to create a personalized meeting schedule message by combining a name input with formatted date and time information.


Drag the example onto the workspace to explore and experiment!



In this example

  1. The Text widget provides the name "John Doe" as a primitive String value
  2. The Template String widget receives the name and combines it with a formatted message using:
    • The input name via {{input.value}}
    • The current date and time using various date helpers:
      • {{date.dayName}} for the day of the week
      • {{date.month}}/{{date.day}}/{{date.year}} for the date
      • {{date.hours}}:{{date.minutes}} for the time
  3. The resulting formatted message is displayed in another Text widget, showing a personalized greeting with the current date and time

 

Using Object Input

This example demonstrates how to create a personalized user account summary by accessing nested properties from a JSON object input.


Drag the example onto the workspace to explore and experiment!



In this example

  1. A JSON object containing user information is provided as input, with nested properties for user details and location
  2. The Template String widget accesses the nested properties using dot notation:
    • {{input.user.firstName}} for the user's first name
    • {{input.user.email}} for the email address
    • {{input.user.location.city}} and {{input.user.location.country}} for the location
    • {{input.user.lastLogin}} for the last login timestamp
  3. The resulting formatted message displays a personalized account summary with all the user's information neatly organized

 

Using Global Variables ($vars)

This example demonstrates how to access global variables using all three notation styles: dot notation, static bracket notation, and dynamic bracket notation.


Drag the example onto the workspace to explore and experiment!



Setting up Global Variables

To use this example, you'll need to create the following Global Variables in the Global Variables Panel:

  • Group variable named user containing:
    • Group variable named profile containing:
      • Text variable named country (e.g., value: "Spain")
  • Text variable named greeting (defines the greeting message)
  • Text variable named team (displays the team name)

In this example

  1. The Button Widget triggers the Text Widget to output a JSON string containing name and variableKey fields
  2. The JSON Parse Widget converts the text string into a JSON object
  3. The Template String Widget builds the message using Global Variables (created and managed in the Global Variables Panel) combined with the parsed input object. The template accesses global variables using all three notation styles:
    • Dynamic bracket notation: {{$vars[input.variableKey]}} - Access using a dynamic key from the input context (the variableKey field contains "greeting", so it accesses $vars.greeting)
    • Dot notation: {{$vars.team}} - Direct access by variable name
    • Static bracket notation: {{$vars["user.profile.country"]}} - Access using string literals (useful for keys with special characters or dots)
  4. The Text Widget displays the final formatted message output

 

Using Secrets in Template Strings

This example demonstrates how to access secrets mapped to the recipe using the $secrets object in a template string.


Drag the example onto the workspace to explore and experiment!



Prerequisites / Setup

To use this example, you'll need to set up secret mapping:

  1. Create (or ensure you already have) a Hub Secret available in the workspace (e.g., TOKEN)
  2. Add a Secret Widget to the recipe and select/declare the secret name used by the workflow (e.g., TOKEN). The widget is used for mapping and does not need to be connected
  3. Open Recipe Secrets (Secret Mapping) and map the required secret to an environment variable:
    • Confirm the required secret name appears (e.g., TOKEN)
    • Select the Context (e.g., develop)
    • Select the matching Environment Variable (e.g., TOKEN)
    • Click Save
  4. After mapping, the secret can be referenced in Template String using dot notation (e.g., {{$secrets.TOKEN}})

In this example

  1. The Secret Widget declares the TOKEN secret used in the recipe and prompts mapping it to an environment variable via the Secret modal
  2. The Button Widget triggers the Template String Widget to process the template
  3. The Template String Widget retrieves the mapped secret value using {{$secrets.TOKEN}} and injects it into the formatted output
  4. The Text Widget displays the final rendered message containing the decrypted secret value

 

Creating a Numbered Task List with $fn()

This example demonstrates how to create a numbered task list using JavaScript array methods within the $fn() helper for formatting each item with proper numbering and conditional formatting.


Drag the example onto the workspace to explore and experiment!



In this example

  1. A JSON object containing user information with name property, a date field, and an array of tasks where each task has a title property is provided as input
  2. The Template String widget uses JavaScript array methods within $fn() to create a personalized task summary:
    • {{input.user.name}} and {{input.date}} for personalized greeting
    • {{$fn("input.tasks.map((task, i, arr) => (i === 0 ? 'First Task 👇\\n' : '') + '✅ Task #' + (i + 1) + ': ' + task.title + (i === arr.length - 1 ? '\\nLast Task ☝️' : '')).join('\\n')")}} to iterate over tasks with numbering and conditional formatting
    • Array methods like map() with i (index) and arr (array) parameters for 1-based numbering and first/last detection
    • Conditional logic within the $fn() using i === 0 for the first task and i === arr.length - 1 for the last task
    • {{$fn("input.tasks.length")}} to display the total number of tasks
  3. The resulting output shows a personalized message with a numbered task list, demonstrating how JavaScript array methods within $fn() can be used to create rich, structured content from array data with full programming flexibility

 

📌 Additional Notes

  • The Template String widget uses JavaScript expression syntax with expr-eval for variable substitution and calculations
  • When using the Text format (default), special characters in the output are HTML-encoded (e.g., / becomes /)
  • To prevent HTML escaping: Use triple curly braces {{{variable}}} instead of double curly braces {{variable}} when you need unescaped output (useful for file paths, URLs, or when you want literal characters)
  • The JSON format is useful when you need to generate structured data
  • Date and time values are always in the local timezone unless explicitly using UTC helpers (e.g., {{date.UTCHours}})
  • For primitive input types (string, number, boolean), use {{input.value}} to access the value
  • Nested object properties can be accessed using dot notation (e.g., {{input.user.profile.name}})
  • Array values can be accessed using JavaScript array syntax (e.g., {{input.user.pets[0]}})
  • Bracket notation supports quoted strings for properties with spaces or special characters (e.g., {{input['full name']}}, {{input["user age"]}})
  • The Template String widget automatically handles undefined or null values by replacing them with empty strings
  • Template variables are case-sensitive (e.g., {{input.user.firstName}} is different from {{input.user.firstname}})
  • Use $fn() helper for complex array operations, calculations, and conditional logic with full JavaScript capabilities
  • Global variables are accessible via {{$vars.variableName}} or {{$vars["variableName"]}} syntax, with support for dynamic keys like {{$vars[input.key]}}
  • Basic operators and Math functions are available within expressions (e.g., {{input.length > 0}}, {{round(input.price)}})
  • The $fn() helper provides access to the full JavaScript runtime for advanced operations

Expression Syntax Support

✅ Supported directly in {{}} expressions:

  • Basic arithmetic: {{5 + 3}}, {{input.price * 1.2}}
  • Comparisons: {{input.length > 0}}, {{price >= 100}}
  • Logical operators: {{true and false}}, {{not isEmpty}}
  • Math functions: {{round(3.7)}}, {{max(1, 5, 3)}}, {{sqrt(16)}}
  • Math constants: {{PI}}, {{E}}
  • Simple property access: {{input.name}}, {{user.age}}
  • Ternary operator: {{input.isTrue ? 'yes' : 'no')}}

❌ Requires $fn() helper:

  • JavaScript logical operators: {{$fn("true && false")}}
  • String methods: {{$fn("input.name.toUpperCase()")}}
  • Array methods: {{$fn("items.join(', ')")}}
  • Array property access on nested arrays: {{$fn("input.tasks.length")}} (for arrays, use $fn(); object properties like {{input.user.profile.settings.theme}} work directly)

 

Glossary

  • ISO 8601

    An international standard for representing dates and times in a consistent format (YYYY-MM-DDTHH:mm:ss.sssZ).

  • UTC

    Coordinated Universal Time, the primary time standard by which the world regulates clocks and time. UTC is independent of time zones and provides a consistent reference point for global time coordination.

  • Global Variables Panel

    A centralized interface component in Kemu that provides a single location to create, configure, and manage Global Variables used throughout recipes. Global Variables are values that persist during recipe execution and can be accessed and modified from any widget in the workflow or directly from the panel interface. The panel enables centralized variable management, runtime control, configuration sharing across workflows, and hierarchical organization of related variables. Variables created in the panel are immediately available to widgets, expressions, and services throughout the recipe. Users can open the Platform Help from the left sidebar (question mark icon) to find more information about the Global Variables Panel