Virtual Happy Hour this month, Jun 28, we'll be getting a sneak preview at our soon to launch SaaS CMS!

Try our conversational search powered by Generative AI!

Updating the value of hidden fields based on page properties

Vote:
 

Hi, 

For one of my customers they want to be able to add a series of properties to a page, and then when a form is included on the page, the hidden values are added to a series of hidden fields (This is essentially so that they can have one form used on thousands of pages, and not need 1000s of identical forms with different hidden values), has anyone ever done anything like this?

Thanks in advance

Andy

#290621
Oct 26, 2022 16:19
Vote:
 

You would need to create a custom formfield inheritting the following class "PredefinedHiddenElementBlock"

Here is an example of us getting a value from the parent page and setting in the form submission 

    [ContentType(DisplayName = "Inherited Element Block", 
        GUID = "0882d17f-4034-4e41-8f58-6890668607b3",
        Description = "Inherited Element Block - Value is supplied by the parent page", 
        GroupName = ConstantsFormsUI.FormElementGroup, 
        Order = 2900)]
    public class InheritedElementBlock : PredefinedHiddenElementBlock
    {
        [Display(Name = "Parent page parameter", Order = 10)]
        [Required]
        public virtual string ParentPageParameter { get; set; }

        [Ignore]
        public bool? IsMatch
        {
            get
            {
                var pageRouteHelper = ServiceLocator.Current.GetInstance<IPageRouteHelper>();
                var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>();
                IFormParameters formParametersPage = null;
                try
                {
                    if (pageRouteHelper != null && pageRouteHelper.ContentLink != null)
                    {
                        var parentPage = contentLoader.Get<IContentData>(pageRouteHelper.ContentLink);
                        if (parentPage != null)
                        {
                            formParametersPage = parentPage as IFormParameters;
                        }
                        else return null;
                    }
                    else return null;
                }
                catch (NullReferenceException)
                {
                    //PageRouteHelper throws null reference exceptions if in block (not page) edit mode
                }

                if (formParametersPage != null && formParametersPage.FormParameters != null)
                {
                    return formParametersPage.FormParameters.Where(x => x.Parameter == this.ParentPageParameter).Select(x => x.Value).Any();
                }

                return null;
            }
        }

        public override string GetDefaultValue()
        {
            var pageRouteHelper = ServiceLocator.Current.GetInstance<IPageRouteHelper>();
            var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>();
            IFormParameters formParametersPage = null;
            try
            {
                if (pageRouteHelper != null && pageRouteHelper.ContentLink != null)
                {
                    var parentPage = contentLoader.Get<IContentData>(pageRouteHelper.ContentLink);
                    if (parentPage != null)
                    {
                        formParametersPage = parentPage as IFormParameters;
                    }
                }
            }
            catch (NullReferenceException)
            {
                //PageRouteHelper throws null reference exceptions if in block (not page) edit mode
            }

            if (formParametersPage != null && formParametersPage.FormParameters != null)
            {
                return formParametersPage.FormParameters.Where(x => x.Parameter == this.ParentPageParameter).Select(x => x.Value).FirstOrDefault();
            }

            return "";
        }
    }
#290626
Oct 26, 2022 22:37
Vote:
 

And another more simpler example based on Query String Parameters 

    [ContentType(
        DisplayName = "Query string hidden field block",
        GUID = "6F3C2D4F-4EA1-465A-A96B-10061B7DD962",
        Description = "Query string hidden field block")]
    [ImageUrl("~/Resources/icons/Formfields/predefinedhiddenelementblock.png")]
    public class QueryStringHiddenFieldBlock : PredefinedHiddenElementBlock
    {
        [Display(
            Name = "Query string parameter",
            Order = 100)]
        [Required]
        public virtual string QueryStringParameter { get; set; }

        [Ignore]
        public override string PredefinedValue { get; set; }

        [Ignore]
        public override string Label { get; set; }
    }
#290627
Oct 26, 2022 22:38
Vote:
 

We had a similar requirement. We have some product details pages as part of a product catalog ... no ecommerce/shop functionality. But you could order sample request for the specific products and here we use Optimizely Forms with IExternalSystem (to integrate to CRM). 

We created a couple of custom form element blocks and had some javascript event and listeners to inject data from the page into the these custom element fields. These custom element block all inherited from  HiddenElementBlockBase with no added logic other than their own razor views with the js listener logic.

Caution: users with html knowledge will be able to change the values of the hidden fields. I did consider adding checksum values and having a field validators validating that checksum. But for our specific scenario we didn't need to.

#290842
Edited, Oct 31, 2022 11:06
Vote:
 

Depending on what you want to do, you could also hook into the CustomActorsExecutingService.  In this case, a client wants 1 Optimizely Form to be reused on numerous "People Pages".  With the form submitting to the relevant person that the page represents.

namespace ClientName.Features.Pages.Person;

using ClientName.Features.Common.Pages;

using EPiServer;
using EPiServer.Core;
using EPiServer.Forms.Core.Models;
using EPiServer.Forms.Core.PostSubmissionActor;
using EPiServer.Forms.Implementation.Actors;
using EPiServer.Forms.Implementation.Elements;

using Microsoft.AspNetCore.Http;

public class CustomActorsExecutingService : ActorsExecutingService
{
    private readonly IContentLoader _contentLoader;

    private const string HostedPageKey = "SYSTEMCOLUMN_HostedPage";

    public CustomActorsExecutingService(IContentLoader contentLoader)
    {
        _contentLoader = contentLoader;
    }

    public override IEnumerable<IPostSubmissionActor> GetFormSubmissionActors(
        Submission submission, 
        FormContainerBlock formContainer, 
        FormIdentity formIden,
        HttpRequest request, 
        HttpResponse response, 
        bool isFormFinalizedSubmission)
    {
        var actors = base.GetFormSubmissionActors(submission, formContainer, formIden, request, response, isFormFinalizedSubmission).ToList();

        var personPage = GetPersonPage(submission);
        var emailActor = actors.OfType<SendEmailAfterSubmissionActor>().FirstOrDefault();

        if (personPage != null && emailActor != null)
        {
            ProcessEmailActor(emailActor, personPage);
        }

        return actors;
    }

    private PersonPage? GetPersonPage(Submission submission)
    {
        if (submission.Data.ContainsKey(HostedPageKey) && int.TryParse(submission.Data[HostedPageKey].ToString(), out var hostedPageId))
        {
            var hostedPageReference = new ContentReference(hostedPageId);
            if (_contentLoader.TryGet<PersonPage>(hostedPageReference, out var personPage))
            {
                return personPage;
            }
        }

        return default;
    }

    private static void ProcessEmailActor(SendEmailAfterSubmissionActor emailActor, PersonPage personPage)
    {
        if (emailActor.Model is IEnumerable<EmailTemplateActorModel> actorModels)
        {
            foreach (var actorModel in actorModels)
            {
                if (string.IsNullOrWhiteSpace(actorModel.FromEmail) || string.Equals(actorModel.FromEmail, "person", StringComparison.CurrentCultureIgnoreCase))
                {
                    actorModel.FromEmail = personPage.ContactEmailAddress;
                }

                if (string.IsNullOrWhiteSpace(actorModel.ToEmails) || string.Equals(actorModel.ToEmails, "person", StringComparison.CurrentCultureIgnoreCase))
                {
                    actorModel.ToEmails = personPage.ContactEmailAddress;
                }
            }
        }
    }
}
#292521
Dec 01, 2022 13:35
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.