The Calculations field is a read-only field that takes content from other fields' content. There's loads you can do, from arithmetic, comparing values and even logic. Keep reading on the docs.
You might like to include your own logic for how values in the Calculations field are treated. Under the hood, we use a JavaScript implementation of the Symfony Expression Syntax (opens new window) for handling parsing of the formula you provide for the Calculations field. You can even write your own, via JavaScript — which is what we're covering in this guide, along with how to use events to modify data.
Let's look at some practical examples.
​Currency#
You might be referencing two Number fields in your Calculations field. Something like:
{fieldA} + {fieldB}
{# Given `fieldA` = 10 and `fieldB` = 5, outputs 15 #}
But what if we wanted to format this as a currency value, say as USD? We can do this with the fields' afterEvaluate
JS event. This event is fired every time a referenced field's value changes — so in this case whenever fieldA
or fieldB
changes values.
So firstly, let's create 3 fields:
- Number (handle
fieldA
) - Number (handle
fieldB
) - Calculations (handle
result
)
Ensure that the result
field has the formula {fieldA} + {fieldB}
by picking the other two Number fields with the variable picker.
Insert the following JavaScript on the page where your form is rendered.
// Fetch the Calculations field we want to format values for
const $field = document.querySelector('[data-field-handle="result"]');
// Listen to every time the formula is evaluated
$field.addEventListener('afterEvaluate', function(e) {
const formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
});
e.detail.result = formatter.format(e.detail.result);
});
Here, we bind the afterEvaluate
event to the result
field. This will fire after the evaluation has run, and we have the result. In this case, we just want to format it, so we take the result (e.detail.result
) and run it through our formatter, then set that value.
Rendering the field, we'll now see $0.00
as soon as it loads (rather than 0
), and the value will be shown as a currency!
​Rounding#
In almost an identical method to the above, we might also like to round numbers.
// Fetch the Calculations field we want to format values for
const $field = document.querySelector('[data-field-handle="result"]');
// Listen to every time the formula is evaluated
$field.addEventListener('afterEvaluate', function(e) {
e.detail.result = Math.round(e.detail.result);
});
Given the values 1.276
and 7.682
for fieldA
and fieldB
, respectively — the result will be 9
.
​Modifying data#
So far, we've covered modifying the result generated by the evaluation, but we can also modify the content used in the formula, and the formula itself using the beforeEvaluate
JS event.
Let's say the fieldA
in our example has some validation logic you want to enforce. If the value entered is over 20, then you want that to be the maximum value. You could of course enforce this on the fieldA
Number field itself, but this is just an example after all 😉
Insert the following JavaScript on the page where your form is rendered.
// Fetch the Calculations field we want to format values for
const $field = document.querySelector('[data-field-handle="result"]');
// Listen to every time the formula is evaluated
$field.addEventListener('beforeEvaluate', function(e) {
const formula = e.detail.formula;
const variables = e.detail.variables;
if (e.detail.variables.field_fieldA > 20) {
e.detail.variables.field_fieldA = 20;
}
});
You can see we're modifying the variables
object to enforce our logic. Every value in the variables object is prefixed by field_
, then the field handle. These are the source fields content, used in our formula.
Now, when setting values, fieldA
values can still be entered over 20 (which might be valid for your use case), but the calculations will max out at 20
.
​Advanced usage#
Where the variables
in the previous example were simple numbers, you can also supply these as functions — because JavaScript! We also might like to modify the formula, to get real tricky. 😎
// Fetch the Calculations field we want to format values for
const $field = document.querySelector('[data-field-handle="result"]');
// Listen to every time the formula is evaluated
$field.addEventListener('beforeEvaluate', function(e) {
// Modify the formula (or you could supply this in the field settings)
e.detail.formula = 'field_fieldA + field_fieldB + suffix.myMethod("🔥")';
// Add a new variable `suffix` with a method
e.detail.variables.suffix = {
myMethod: function(string) {
return ' is ' + string;
},
};
});
Given the values 1
and 5
for fieldA
and fieldB
, respectively — the result will be 6 is 🔥
.