Sitecore Forms – Rendering friendly field values for EXM

Sitecore 9.2 introduces the newly and improved submit action Send Email Campaign Message that can be used within Sitecore Forms, to send an EXM Campaign message to a contact. Within this submit action you can configure which fields from the form should be passed to EXM as an token, after which you can use the field within your email. So far so good….

The values that are passed to EXM only appear correct when you are using simple field types like text, number or email fields. Complex types like the Radio Button List, Checkbox List just output the raw values that you’ve set as value. For example; a Radio Button List which uses a list of Sitecore Items as datasource and that uses using the name of the item as Name and the id of the item as Value, will just render the ID of the items within your EXM email. That’s not a really friendly way of showing the form values to a user 😉

The transformFormsCustomToken pipeline

When Sitecore created the functionality, they knew that something had to be done with the form fields, but they didn’t implemented anything by default. They did however create a pipeline that is called to transform the field values, to which we can add our own processors. For most scenario’s my guess is that you should have enough by using the processors from my sample code below. This example includes support for collections, dates, booleans and the default functionality of Sitecore will just call the ToString method when no token transformation is applied.

The code below works as follows:

  1. If the value is a DateTime or a collection of DateTime it will convert the value to ToShortDateString.
  2. If the value is a Guid or a collection of Guid, it will try to retrieve the Sitecore item and return the DisplayName.
  3. If the value is Boolean or a collection of Boolean, it will get the boolean.true or boolean.false value from the dictionary.
  4. If the value is a ICollection, get the string value of the item and join all values seperated with a comma.

TransformValueBase.cs

public abstract class TransformValueBase
{
    public virtual void Process(TransformFormsCustomTokenArgs args)
    {
        var tokenValue = args.TransformedTokenValue ?? args.OriginalTokenValue;
        if (tokenValue is IEnumerable enumerable)
        {
            List<string> values = new List<string>();
            foreach (var fieldValue in enumerable)
            {
                var value = ResolveValue(fieldValue);
                if (value == null)
                {
                    return;
                }

                values.Add(value);
            }

            if (values.Any())
            {
                args.TransformedTokenValue = values;
            }
        }
        else
        {
            var value = ResolveValue(tokenValue);
            if (value != null)
            {
                args.TransformedTokenValue = value;
            }
        }
    }

    protected abstract string ResolveValue(object value);
}

TransformDateValue.cs

public class TransformDateValue : TransformValueBase
{
    protected override string ResolveValue(object value)
    {
        if (value is DateTime dateTime)
        {
            return dateTime.ToShortDateString();
        }

        return null;
    }
}

TransformGuidValue.cs

public class TransformGuidValue : TransformValueBase
{
    private readonly ISitecoreContextService _sitecoreContextService;

    public TransformGuidValue(ISitecoreContextService sitecoreContextService)
    {
        _sitecoreContextService = sitecoreContextService;
    }

    protected override string ResolveValue(object value)
    {
        if (Guid.TryParse(value.ToString(), out var id))
        {
            return _sitecoreContextService.Database.GetItem(new ID(id))?.DisplayName;
        }

        return null;
    }
}

TransformBooleanValue.cs

    public class TransformBooleanValue : TransformValueBase
    {
        protected override string ResolveValue(object value)
        {
            if (value is bool boolean)
            {
                return Sitecore.Globalization.Translate.Text($"boolean.{boolean.ToString().ToLowerInvariant()}");
            }

            return null;
        }
    }

TransformICollectionValue.cs

public class TransformICollectionValue
{
    public void Process(TransformFormsCustomTokenArgs args)
    {
        var tokenValue = args.TransformedTokenValue ?? args.OriginalTokenValue;
        if (tokenValue is ICollection collection)
        {
            List<string> stringValues = new List<string>();
            foreach (var value in collection)
            {
                var stringValue = value.ToString();
                if (!string.IsNullOrEmpty(stringValue))
                {
                    stringValues.Add(stringValue);
                }
            }

            args.TransformedTokenValue = string.Join(", ", stringValues);
        }
    }
}

TokenTransformation.config

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:x="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/" xmlns:exmEnabled="http://www.sitecore.net/xmlconfig/exmEnabled/" xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore exmEnabled:require="yes" role:require="Standalone or ContentDelivery">
    <pipelines>
      <group groupName="exm.sendEmailSubmitAction">
        <pipelines>
          <transformFormsCustomToken>
            <processor type="Example.TransformRepeatableFieldValue, Example" resolve="true"/>
            <processor type="Example.TransformDateValue, Example" resolve="true"/>
            <processor type="Example.TransformGuidValue, Example" resolve="true"/>
            <processor type="Example.TransformBooleanValue, Example" resolve="true"/>
            <processor type="Example.TransformICollectionValue, Example" resolve="true"/>
          </transformFormsCustomToken>
        </pipelines>
      </group>
    </pipelines>
  </sitecore>
</configuration>

Leave a Reply

Your email address will not be published.