Wednesday, December 19, 2018

Passing Context Item Information as hidden field values with Sitecore 9 Forms

Recently I was working with Sitecore Forms in Sitecore 9 installation and needed to pass context item information (Item Name, Item ID) where a given form is implemented.

After investigating, there were no default way/field to achieve this and had to implement custom field type for that.

Following is the code implementation to get the hidden field and to populate the hidden field.

public class FormDataSubmitAction : SubmitActionBase<string>
{
        public FormDataSubmitAction(ISubmitActionData submitActionData) : base(submitActionData)
        {
        }
        protected override bool Execute(string data, FormSubmitContext formSubmitContext)
        {
            Assert.ArgumentNotNull(formSubmitContext, nameof(formSubmitContext));
          
            if (!formSubmitContext.HasErrors)
            {
                StringBuilder message = new StringBuilder();
                var parameters = new NameValueCollection();
              
                foreach (IViewModel field in formSubmitContext.Fields)
                {
                    if(field.FieldTypeItemId.Equals(<CustomHiddenFieldTemplateID>, StringComparison.InvariantCultureIgnoreCase))
                    {
                        AddExtraAttributes(parameters, GetValue(field));
                        continue;
                    }
                    parameters.Add(field.Name, GetValue(field));
                }
                PostData(parameters);
            }
            else
            {
                Logger.Warn(Invariant($"Form {formSubmitContext.FormId} submitted with errors: {string.Join(", ", formSubmitContext.Errors.Select(t => t.ErrorMessage))}."), this);
            }
            return true;
        }
      
        protected override bool TryParse(string value, out string target)
        {
            target = string.Empty;
            return true;
        }
        protected virtual NameValueCollection AddExtraAttributes(NameValueCollection parameters, string contextItemId)
        {
            var contextItem = ItemHelper.GetItem(contextItemId);
            if(contextItem == null)
            {
                return parameters;
            }
            parameters.Add("referring_page", SiteHelper.GetUrl(contextItem));  //You can add more parameters here
            return parameters;
        }
        protected void PostData(NameValueCollection parameters)
        {
            //POST Data to Third-party system
        }
        private static string GetValue(object field)
        {
            return field?.GetType().GetProperty("Value")?.GetValue(field, null)?.ToString() ?? string.Empty;
        }
}


/Views/FormBuilder/FieldTemplates/ContextItemId.cshtml

@using Sitecore.ExperienceForms.Mvc.Html
@model Sitecore.ExperienceForms.Mvc.Models.Fields.StringInputViewModel

@if (!Html.Sitecore().IsExperienceForms())
{
    <input id="@Html.IdFor(m => Model.Value)" name="@Html.NameFor(m => Model.Value)" type="hidden" value="@Sitecore.Context.Item.ID.ToString()" data-sc-field-name="@Model.Name" />
}
else
{
    <div class="form-group">
        <p class="form-control">
            Hidden Sitecore Context Item ID Field
        </p>
    </div>
}


NOTE:
Special thanks to Kamruz Jaman (@jammykam) and Mike Reynolds (@mike_i_reynolds) for pointing me to correct direction.