Pages

Thursday, September 23, 2021

Optimizely Form Events using an Interface Pattern

Much like standard content items in Optimizely CMS, Forms trigger events that can be subscribed to for further customization. You typically subscribe to these events by employing an Initialization Module and attaching an event handler to process the logic you need for each event. This works well for the out-of-the-box Forms, but I have done enough customization of forms that I started employing an Interface pattern to clean it up. I use this same pattern for content events, so I thought I would share my forms approach. 

First, create an Interface to define the pattern for calling the event method on the form. 

There are 4 .NET events triggered by Optimizely forms. An interface for each one needs to be defined with a unique method declaration for the event handler each addresses, as shown below.

[pre class="brush:csharp;class-name:'collapse-box'"]
using EPiServer.Forms.Core.Events;

namespace EpiSandbox.Interfaces
{
    public interface IFormSubmitting
    {
        void OnSubmittingForm(object sender, FormsEventArgs e);
    }
    public interface IFormSubmitted
    {
        void OnSubmissionFinalized(object sender, FormsEventArgs e);
    }
    public interface IFormStepSubmitted
    {
        void OnStepSubmitted(object sender, FormsEventArgs e);
    }
    public interface IFormStructureChanged
    {
        void OnFormStructureChanged(object sender, FormsEventArgs e);
    }
}
[/pre]

Next, an InitializationModule is needed to subscribe to the event handlers. 

The InitializationModule will define the event methods through which the methods on each Form object are called. Each method checks to see if the Form Content object inherits from the proper Interface, and invokes the corresponding method if it does.

[pre class="brush:csharp;class-name:'collapse-box'"]
using EpiSandbox.Interfaces;
using EPiServer.Forms.Core.Events;
using EPiServer.Framework;
using EPiServer.Framework.Initialization;
using EPiServer.ServiceLocation;

namespace EpiSandbox.Initialization
{
    [ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
    public class FormEventsInitializationModule : IInitializableModule
    {
        private Injected<FormsEvents> _formsEvents;

        public void Initialize(InitializationEngine context)
        {
            _formsEvents.Service.FormsSubmitting += OnSubmittingForm;
            _formsEvents.Service.FormsSubmissionFinalized += OnSubmissionFinalized;
            _formsEvents.Service.FormsStepSubmitted += OnStepSubmitted;
            _formsEvents.Service.FormsStructureChange += OnStructureChanged;
        }
        public void Uninitialize(InitializationEngine context)
        {
            _formsEvents.Service.FormsSubmitting -= OnSubmittingForm;
            _formsEvents.Service.FormsSubmissionFinalized -= OnSubmissionFinalized;
            _formsEvents.Service.FormsStepSubmitted -= OnStepSubmitted;
            _formsEvents.Service.FormsStructureChange -= OnStructureChanged;
        }

        private void OnSubmittingForm(object sender, FormsEventArgs e)
        {
            var form = e.FormsContent as IFormSubmitting;
            if (form == null) { return; }
            form.OnSubmittingForm(sender, e);
        }

        private void OnSubmissionFinalized(object sender, FormsEventArgs e)
        {
            var form = e.FormsContent as IFormSubmitted;
            if (form == null) { return; }
            form.OnSubmissionFinalized(sender, e);
        }

        private void OnStepSubmitted(object sender, FormsEventArgs e)
        {
            var form = e.FormsContent as IFormStepSubmitted;
            if (form == null) { return; }
            form.OnStepSubmitted(sender, e);
        }

        private void OnStructureChanged(object sender, FormsEventArgs e)
        {
            var form = e.FormsContent as IFormStructureChanged;
            if (form == null) { return; }
            form.OnFormStructureChanged(sender, e);
        }
    }
}
[/pre]

Finally, inherit from the proper interface and implement the necessary methods to use it.

[pre class="brush:csharp;class-name:'collapse-box'"]
namespace EpiSandbox.Models
{
    [ContentType(DisplayName = "Custom Form Container", GUID = "d6b5bbce-c897-4e4f-bb54-d14cd6b8a3a7", Description = "Custom form container to use in Episerver.",
        GroupName = EPiServer.Forms.Constants.FormElementGroup_Container)]
    [ServiceConfiguration(typeof(IFormContainerBlock))]

    [ImageUrl("~/resources/icons/custom-form-block.jpg")]
    public class StandardFormContainerBlock : FormContainerBlock, IFormSubmitted
    {
        [Ignore]
        [ScaffoldColumn(false)]
        public string MySpecialProperty{ get; set; }

        public void OnSubmissionFinalized(object sender, FormsEventArgs e)
        {
            var submittedEventArgs = e as FormsSubmittedEventArgs;
            MySpecialProperty = "Daved was here";
            // do something with my submission data or form information
        }
    }
}
[/pre]

No comments:

Post a Comment

Share your thoughts or ask questions...