JavaScript
Overview
You can add a JavaScript function for:
- Computing Group Totals (locally or remotely), or fetching a numeric value such as the Num. of items in stock.
- For HTTP requests, e.g. posting a form when clicking a button (see the last example)
Function Argument (Payload)
- Group: describes the Group content.
- Button: describes its parent Group content.
When does it execute?
- Group: on File load, and on payload-relevant changes.
Return Value
- Group: has to be a number (or numeric string) and becomes the Total.
- Button: is ignored.
Technical details
For security, functions run inside Web Workers. Therefore, there are limitations, like no direct DOM manipulation.
The code timeouts after 8 seconds. Therefore, if you open a File that has a JavaScript code error, you’ll see a spinner until it times out. Similarly, if the execution on a Button fails, and the Button has more actions, they’ll execute after the timeout.
Example
This example has Keys (they’re explained in the next section, but take a look at them here first).

Group → Code. The JavaScript editor pre-populates a snippet that sums numeric Items that have Keys. In this example:
function (group) { const side_a = group.side_a.value const side_b = group.side_b.value return side_a + side_b }
After hitting Apply, the Total will be computed by that function. And it will recompute when the Items change.
Payload
The payload, the argument passed to each function, describes the Group that houses the JavaScript function and its children. Each child is a description of either an Item, or a Nested Group.
If you want Items or Totals from other Groups, connect them to the Group with the function.
Hidable children show up in the payload, so you can use them for API keys, tokens, etc.
Like in Formulas, Nested Groups get computed first. Therefore, their Totals are ready to use in the parent payload — asynchronous code is supported.
Tip There’s a Download Payload Mock button that shows the exact argument the function will be called with.
Group (Root or Nested)
key
Stringvalue
Group Total as a NumberstringValue
Group Total as a Stringchildren
Array, in order, of the Items and Nested GroupsisNumeric
Boolean, true if the Group has a numeric Total. As Totals can only be numeric, this is like a hasTotal. But as Items also have anisNumeric
property, this consistent naming is handy for cases like the Max example below
Item
key
Stringvalue
Number if it’s numeric; 1 or 0 if it’s a Checkbox; String otherwisestringValue
struck
Boolean for Strikethroughlabel
StringisNumeric
Boolean
Examples
Sum All
function (group) { return group.children .reduce((sum_so_far = 0, child) => sum_so_far + child.value) }
That function is like Formula Presets → Sum All, but the actual preset does more checks, see the next example.
Max
Equivalent to Formula Presets → Maximum.
Ensures computing on numeric children that aren’t struck. And handles when there are none by returning an empty string.
Although Nested Groups have no struck
property, it’s
safe to filter it.
function (group) { const values = group.children .filter(child => child.isNumeric && !child.struck) .map(child => child.value) return values.length ? Math.max(...values) : '' }
Count children costing 50 or more
function (group) { return group.children .filter(child => child.value >= 50) .length }
Sum children costing over 50
function (group) { return group.children .filter(child => child.value > 50) .reduce((sum_so_far = 0, child) => sum_so_far + child.value) }
Stepped Discounts
The price gets a 15% discount if buying 10 or more, or 25% on 50+.

The Auxiliary Group code:
function (group) { const num_of_items = group.num_of_items.value const base_price = group.base_price.value const discounts = group.volume_discounts.children let discount_so_far = 0 for (const discount of discounts) if (num_of_items >= Number(discount.label)) discount_so_far = discount.value return base_price * (1 - discount_so_far) }
Examples with HTTP Requests
This repository has the server-side handlers for these examples.
HTTP Get

function (group) { const product_id = group.product_id.value return fetch(`http://localhost:7000/in-stock-count/${product_id}`) .then(response => response.json()) .then(data => data.count) .catch(console.error) }
HTTP Post

function (group) { return fetch('http://localhost:7000/hypotenuse', { body: JSON.stringify(group), method: 'POST', headers: new Headers({ 'Content-Type': 'application/json' }) }) .then(response => response.json()) .then(data => data.hypotenuse) .catch(console.error) }
HTTP Post Button

function (group) { return fetch('http://localhost:7000/form-submit', { body: JSON.stringify(group), method: 'POST', headers: new Headers({ 'Content-Type': 'application/json' }) }) .then(() => '') .catch(console.error) }