Using your answer as inspiration I expanded upon it by creating a custom submit action that would store all the form values in the session and then a custom form element that would be placed after the form submit button and replace all given placeholder text dynamically using the fields name.
The custom submit action stores all the values in a list of key values pairs with the name of the field being the key. Input fields that would return a list are processed to return a comma separated string.
public class StoreFormInSessionSubmit : SubmitActionBase<string>
{
public StoreFormInSessionSubmit(ISubmitActionData submitActionData) : base(submitActionData)
{
}
protected override bool TryParse(string value, out string target)
{
target = string.Empty;
return true;
}
protected override bool Execute(string data, FormSubmitContext formSubmitContext)
{
Assert.ArgumentNotNull(formSubmitContext, nameof(formSubmitContext));
if (!formSubmitContext.HasErrors)
{
Logger.Info($"Form {formSubmitContext.FormId} submitted successfully.");
var formValues = GetFormValues(formSubmitContext.Fields);
HttpContext.Current.Session["form"] = formValues;
}
else
{
Logger.Warn($"Form {formSubmitContext.FormId} submitted with errors: {string.Join(", ", formSubmitContext.Errors.Select(t => t.ErrorMessage))}.");
}
return true;
}
private List<KeyValuePair<string, string>> GetFormValues(IList<IViewModel> form)
{
var formValues = new List<KeyValuePair<string, string>>();
foreach (var inputField in form)
{
var inputFieldValue = GetFormValue(inputField);
formValues.Add(new KeyValuePair<string, string>(inputField.Name, inputFieldValue));
}
return formValues;
}
private string GetFormValue(object field)
{
var value = field?.GetType().GetProperty("Value")?.GetValue(field, null);
if (value is IList)
{
var enumerableValue = value as IList<string>;
return string.Join(",", enumerableValue.ToArray());
}
else
{
return value?.ToString() ?? string.Empty;
}
}
}
The custom form element is simply based of the standard text element but when rendering the text value, loops through all the key value pairs retrieved from the session and replaces all placeholder text found in the form element.
[Serializable]
public class PersonalizedText : FieldViewModel
{
public string Text { get; set; }
protected override void InitItemProperties(Item item)
{
base.InitItemProperties(item);
Text = StringUtil.GetString(item.Fields["Text"]);
if (!string.IsNullOrEmpty(Text))
{
var formValues = (IList<KeyValuePair<string, string>>) HttpContext.Current.Session["form"];
ReplacePlaceholderText(formValues);
}
}
protected override void UpdateItemFields(Item item)
{
base.UpdateItemFields(item);
item.Fields["Text"]?.SetValue(Text, true);
}
private void ReplacePlaceholderText(IList<KeyValuePair<string, string>> formValues)
{
if (formValues != null && formValues.Any())
{
foreach (var formValue in formValues)
{
var placeholder = '*' + formValue.Key + '*';
Text = Text.Replace(placeholder, formValue.Value);
}
}
}
For reference:
Creating a custom submit action
Creating a custom form element