You are here

Calculate a value from options field in Webform custom composite element with Twig - Drupal 8

Recently, I was creating an event registration Webform. I created a custom composite field with the fields needed for each registrant: first name, last name, and a set of three radio options for their organization status: member, non-member, membership fee included in event registration. Each status has a different registration fee.

I then wanted to create a computed Twig field that would calculate the total registration fee by getting the data from the chosen radio option for each attendee and adding it up. This proved surprisingly tricky.

First, neither of the Twig variables that you are supposed to be able to use to get data from sub-element options worked:

{{ data.composite_element_key.subelement_key }}
{{ }}

I'm not sure if it's because the subelement is an options element.

I was able to print out the data using the Webform token function:

{{ webform_token('[webform_submission:values:composite_element_key:delta:subelement_key]', webform_submission, [], options) }}

However, this just printed out an undifferentiated string with the field label, value, and key for each selected option mushed together:

NJSCA Membership: Non-NJSCA membernjsca_membershipNJSCA Membership: Non-NJSCA membernjsca_membershipNJSCA Membership: Include 1-year NJSCA membershipnjsca_membershipnjsca_membership

To achieve what I wanted, I had to set up some filters to format that data as an array without the field label or key, set a variable for the registration fee, and then create a for loop to loop over the values in the array and increase the registration fee variable by the correct amount for each selected option.

Note: this is all done in the "Computed value/markup" field in a Webform Computed Twig element.

First, we set up a "data" variable that grabs the selected options of our custom composite radio buttons:

{% set data = webform_token('[webform_submission:values:attendees:delta:njsca_membership]', webform_submission, [], options) %}

Next, we create another variable from this data, with Twig filters. We use the Twig replace filter to remove the field label and the double field key, which shows up at the end of the string, with single quotes with nothing between them, essentially stripping them out. After the replace filters run, we end up with a string consisting of the label values for each radio option separated by the field key. We use the Twig split filter to break up the string at each instance of the key value into an array:

{% set array = data|replace({'NJSCA Membership: ': '', 'njsca_membershipnjsca_membership': ''})|split('njsca_membership') %}

The double end key seemed to be showing up because my custom composite was set (under the "advanced" tab in the element edit screen) to allow users to add more items, and the default is to add 1 more item at a time. Changing it to not allow adding more items removed the double key, so your custom composite element may be different if it does not allow adding or if you change the default to more than one (I did not test that).

Before removing the double key, it created two extra empty items in the array. Twig seems to add a new item for every instance of the split delimiter, even if there's no text after it. If you are not allowing adding of more items, you will still have the key value at the end of your string and, I believe, end up with one empty item. You might need to use the Twig last filter to remove it before splitting the string.

Now, if we print out our array using {{ array|join(' ') }}, we'll see:

Non-NJSCA member Non-NJSCA member Include 1-year NJSCA membership

That's better. Now to get the calculated total registration value, we need to first set a "fee" variable which we'll initialize at 0, then loop over every item in the "array" array (yes, I could have named it better), and depending on their value, increment the fee variable. We will then print the fee variable at the end so registrants can see what they have to pay. Important: the "Automatically update the computed value using Ajax" option in the field settings should be checked so the value will update on the fly as users choose different options.

The complete code is as follows (with generic field names). The "i" values are the name(s) of your sub-element options:

{% set data = webform_token('[webform_submission:values:composite_field_key:delta:subelement_key]', webform_submission, [], options) %}
{% set array = data|replace({'Composite field label: ': '', 'subelement_keysubelement_key': ''})|split('subelement_key') %}
{% set fee = 0 %}
{% for i in array %}
  {% if i == 'Option 1 name %}
    {% set fee = fee + 60 %}
  {% elseif i == 'Option 2 name' %}
    {% set fee = fee + 80 %}
  {% elseif i == Option 3 name' %}
    {% set fee = fee + 90 %}
  {% endif %}
{% endfor %}
{{ '$' ~ fee ~ '.00' }}

Note that I had to add the dollar sign and trailing zeroes to the printed fee variable using Twig functions. Adding the characters as text or putting HTML tags in the field broke it completely, to the point where I had to delete and re-add it, and style it with CSS. I think it must be a Webform bug.

If all goes well, you should be able to see your "Total registration fee" field (or whatever you call it) updating as you select different options!

Add new comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.