Use Twig to create interactive webform calculations
We recently spoke with Ryan Jones from TAPS goClub group about a fascinating project to show commuters just how much pollution they are individually contributing to the environment. In addition to the eye-opening data it provides, the webform created by Ryan and his colleague Ramon Zavala also provides a perfect example of how you can incorporate calculations into your forms and share them with your users.
The method for incorporating Twig into your webforms is worth knowing and we'll recreate Ryan and Ramon's form for you so you can understand the process.
First, what is Twig?
Twig is a template engine specifically for the PHP programming language. This probably doesn't do much to clear this up for you, so, to put this more simply, Twig allows you to create reusable snippets of code containing placeholder tokens that can be saved as templates to output information in a structured way.
Example with tokens in bold:
<p><a href="{{ id }}">{{ content_title }}</a></p>
Create a Webform
The process begins by creating a basic webform. If you haven't done one before, we recommend you begin with Understanding Webforms, available in the Training for Everyone section.
- Navigate to Manage » Structure » Webforms.
- Click the + Add webform button.
- Provide a title. We'll use their original name and call ours 'Commute Calculator'.
- Click Save to continue.
- From within your new form's Build tab, add the following using the + Add element button:
- Number field (or Text with number_format conversion) - titled Roundtrip Miles Per Day
- Change Key [Edit} - commute_distance (this is the machine name of your field)
- Limited: 1
- Min/Max Length: 1 / 3
- Size: 3
- Input mask: Decimal
- Field is required
- Number field (or Text with number_format conversion) - titled Fuel Efficiency
- Limited: 1
- Min/Max Length: 1 / 2
- Input mask: Decimal
- Field is required
- Number field (or Text with number_format conversion) - titled Price Per Gallon of Gas
- Change Key [Edit} - price_for_gas
- Limited: 1
- Min/Max Length: 1 / 6
- Placeholder: $
- Input mask: Decimal
- Field is required
- Number field (or Text with number_format conversion) - titled Days of Commuting Per Month
- Change Key [Edit] - days_of_work
- Limited: 1
- Min/Max Length: 1 / 2
- Placeholder: Number of days
- Input mask: Decimal
- Field is required
- Number field (or Text with number_format conversion) - titled Roundtrip Miles Per Day
This outputs the following elements in your form's list:
Understanding how to read and write Twig calculations
Here is an example of one of the calculations we're going to use:
{{ (data.commute_distance / data.fuel_efficiency)|round(1, 'ceil') }} gal used per day
As the calculation term suggests, this is actually a mathematical equation, so we have to keep that fact in mind as we proceed and understand how our elements are written and structured so we get the output we expect to see. What follows is a breakdown of each of the parts that make up the above calculation.
{{ token }}
When you see double braces, this a token or a placeholder. The token, if referencing a specific form field, should include the field's Key machine name. In programming, we would call this a variable; a container for a value we want, but we won't know what it is until the equation is calculated.
{{ data.token }}
We declare the type of object this information represents. We're telling the template engine that the content we're pulling from the specific form field is of the Data object type. If you're not sure which to use, you can reference the list in the Help with Twig list below or via the link by the same title directly in the Computer Twig field type in your webform.
- Help with Twig
- Learn about Twig and how it is used in Drupal.
The following variables are available:
{{ webform }}
{{ webform_submission }}
{{ elements }}
{{ elements_flattened }}
{{ data.element_key }}
{{ data.element_key.delta }}
{{ data.composite_element_key.subelement_key }}
{{ data.composite_element_key.delta.subelement_key }}
{{ serial }}
{{ sid }}
{{ uuid }}
{{ token }}
{{ uri }}
{{ created }}
{{ completed }}
{{ changed }}
{{ in_draft }}
{{ current_page }}
{{ remote_addr }}
{{ uid }}
{{ langcode }}
{{ webform_id }}
{{ entity_type }}
{{ entity_id }}
{{ locked }}
{{ sticky }}
{{ notes }}
You can also output tokens using the webform_token() function.
{{ webform_token('[webform_submission:values:element_value]', webform_submission, [], options) }}
{{ ( data.token / data.token ) }}
Just like in math equations, we have to respect the order of operations. In the example, we eventually want to make sure our final number is rounded up to a whole value, but without a way to separate the equation from the roundup function, we might still arrive at a number with a decimal. We want to calculate distance commuted divided by the fuel efficiency first, so we isolate this using brackets, after which it will apply any additional instructions, such as the |round syntax described below to round the number up to a whole number.
{{ ( data.token / data.token ) }} plain text
Anything you add outside of the double braces will be printed out as plain text. In our specific example here, the number outputted by our calculation will be followed by 'gal used per day' to make it clearer for the submitter what the data total is referencing.
{{ ( data.token / data.token ) | round(1, 'ceil') }} plain text
Next, we want to make sure we get a whole number from this equation, so we'll add some additional syntax that instructs the engine to round up so we avoid having any decimal points in our output.
Add Twig to perform the calculations
- While in the Build tab, click on the + Add element button, then search for the Computed Twig element to add each of the following Computed Twig elements:
- Computed Twig - titled Gallons Per Day
- Display on: Both form and viewed submission
- Mode: Auto-detect
- Computed value/markup:
{% if data.fuel_efficiency|number_format > 0 %}{{(data.commute_distance|number_format / data.fuel_efficiency|number_format)|round(1, 'ceil')}}{% else %}0{% endif %} gal used per day - Automatically update the computed value using Ajax: Check
- Computed Twig - titled Cost of Fuel Per Day
- Display on: Both form and view submissions
- Mode: Auto-detect
- Computed value/markup:
{% if data.fuel_efficiency|number_format > 0 %}{{(data.commute_distance|number_format * data.price_for_gas|number_format / data.fuel_efficiency|number_format)|number_format(2, '.', ',')}}{% else %}0{% endif %} spent per day - Automatically update the computed value using Ajax: Check
- Computed Twig - titled Cost of Fuel Per Month
- Display on: Both form and view submissions
- Mode: Auto-detect
- Computed value/markup:
{% if data.fuel_efficiency|number_format > 0 %}{{(data.commute_distance|number_format * data.price_for_gas|number_format * data.days_of_work|number_format / data.fuel_efficiency|number_format)|number_format(2)}}{% else %}0{% endif %} spent per month - Automatically update the computed value using Ajax: Check
- Computed Twig - titled KG of Pollution
- Display on: Both form and view submissions
- Mode: Auto-detect
- Computed value/markup:
{% if data.fuel_efficiency|number_format > 0 %}{{(8.89 * data.commute_distance|number_format * data.days_of_work|number_format / data.fuel_efficiency|number_format)|round(1, 'ceil')}}{% else %}0{% endif %} kg of co2 - Automatically update the computed value using Ajax: Check
- Computed Twig - titled Gallons Per Day
Presentation Change
To pretty up ours, we created a container using the Fieldset element and nested all the Computer Twig fields inside of it, but otherwise this represents almost the exact form built by the goClub site.
Final Thoughts
This is a great way to add dynamic functionality to your webforms; it provides instant gratification to your visitors and, on submission, will store the submitted data for your use. As with all other webforms, you can configure email handlers to submit the data to the location or email account of your choice, or leave it in your site's database to export at a later time.