EPiServer, Episerver Forms, ThisAndThat

Create custom Episerver Forms container

In this blog post I’ll show you how you can create a custom Episerver Forms form container block. Then I will extend it having custom properties to enter the Google Tag Manager related form submit event information.

This is another approach to my previous GTM blog post where I needed to be able to add the information to already existing forms – in that case I created new Episerver Forms block element to add the information.

Getting started

First thing is to install the Episerver Forms NuGet package from Episerver NuGet feed to your project. At the time of writing the latest Episerver Forms NuGet package version is 4.24.0 so I’ll be using that in this sample.

Episerver has instructions to create the custom form container block on their instructions page but the instructions currently make some assumptions and skip the information what you should copy as the base for the customized view file. Related to this is also the instruction to create a two column form container block.

So when you install the Episerver Forms package it will add its files to your project under the ‘modules/_protected‘ folder. The package adds two folders: ‘EPiServer.Forms‘ and ‘EPiServer.Forms.UI‘.

In the EPiServer.Forms.UI folder will be a zip package EPiServer.Forms.UI.zip which contains the JavaScript, CSS, etc. resource files needed by the ‘Episerver edit‘ view.

In the EPiServer.Forms folder will be a zip package ‘EPiServer.Forms.zip‘ which contains the embedded language files, resources for the view templates and more importantly the default Episerver Forms view templates (.ascx files) to render the container and form elements. This zip file contains the ‘FormContainerBlock’ view file that should be copied as the base for our custom view. The folder also contains the ‘Forms.config‘ file that can be used to configure Episerver Forms.

I use the Alloy MVC (the one you can create from the Episerver Visual Studio extension) site in the sample, so its default project structure is used.

Create block, controller and view for the custom form container

We need to implement a custom block to be the container for Forms element blocks. We also need to have a custom controller for our new container block and then a view that renders our container.

Container block implementation

Our custom Forms container block needs to inherit the Episerver base class ‘EPiServer.Forms.Implementation.Elements.FormContainerBlock’.

Create a new folder called ‘Forms‘ under the ‘Models‘ folder. Then add a new Episerver ‘Block Type‘ (using VS add new item) there called ‘SiteFormsContainerBlock‘. Add using statement ‘EPiServer.Forms.Implementation.Elements‘ to the code file and change your block to inherit the ‘FormContainerBlock‘ class. Next edit the ContentType attribute, add a description for your block (info to editors) and then also set this blocks group to be the same as the default container blocks group is (GroupName = EPiServer.Forms.Constants.FormElementGroup_Container).

We also need to tell Episerver about our custom container, so we need to add the ServiceConfiguration attribute to our class: [ServiceConfiguration(typeof(IFormContainerBlock))]. You need to add using statements for ‘EPiServer.Forms.Core’ and ‘EPiServer.ServiceLocation’.

Next we add two custom properties to the container: Google Tag Manager form name and category name. In this sample I will have just two string properties where the editor enters the values but for example for the category a list of possible values could be used (like I used in the previous post the GtmSelectionFactory).

Controller implementation

Next step is to implement the controller for our custom container block. Episerver has a base class for this, so our controller should inherit the ” class.

Add new controller under folder ‘Controllers’ using the Episerver  ‘Block Controller (MVC)’ template and name the new controller ‘SiteFormsContainerBlockController’. Add using statements: ‘EPiServer.Forms.Implementation.Elements‘ and ‘EPiServer.Forms.Controllers‘. Switch the new controller to inherit FormContainerBlockController class and change the type for the index method to ‘FormContainerBlock’ currentBlock. Change the Index method implementation to use ‘return base.Index(currentBlock);’

View implementation

So here comes the part where we implement our custom view for the container. First step is to get our “base” view implementation. This is the hacky part, we need to extract the Episerver implementation from the EPiServer.Forms.zip file and then copy paste it as our implementation.

I’ll use the default location for custom Forms view files which is defined in the ‘modules\_protected\EPiServer.Forms\Forms.config‘, see the ‘formElementViewsFolder‘ value. So next create folder ‘~/Views/Shared/ElementBlocks’ and add new view file named ‘FormContainerBlock’, use the Episerver ‘Block Template (Web Forms)‘ to add the view file. Delete the created .ascx.cs and .ascx.designer.cs files for the FormContainerBlock.ascx.

Extract the default implementation to a temporary location: open the EPiServer.Forms.zip file in your favorite archiving tool and extract the ‘Views\ElementBlocks\FormContainerBlock.ascx‘ to temporary location. Open the extracted file in a text editor, copy the file content and paste the text to the just created .ascx file in Visual Studio. Next change the ViewUserControl<FormContainerBlock> to use our custom class: SiteFormsContainerBlock and add using statement for the SiteFormsContainerBlock namespace.

Next we will add the custom properties as data-* properties to the html form element and use custom JavaScript to pull the values from the form when succesful submit is done and create the submission event to Google Tag Manager. See the added data-gtm-formname and data-gtm-formcategory in the below FormContainerBlock.ascx code file.

Last is the JavaScript file that will extract the data-* attribute values from the form when it is submitted.

So this is how it looks in action

custom-forms-container-block-ui
Custom GTM properties on own tab in the form container

In browser console we can see the values taken from data-* attributes and the GTM form submission event triggered.

custom-forms-container-block-js-event

Wrapping it up

As can be seen from the sample, it is quite easy to implement your own custom Episerver Forms container block but it is hack as you need to copy paste the orginal view code to your implementation and modify it. In the long run maintaining the Episerver Forms updates to the view code and synching those back to your custom code might become a nightmare or at least an extra step each time you update the Episerver Forms NuGet package(s).

As a side note you might have spotted in the view file code that Episerver supports rendering the form using HTML div-element. The sample code will inject the data-* attributes also to the div-element and the JavaScript works the same for that case too. To use div-element for the form you need to change the Forms.config value renderingFormUsingDivElement=”false” to value true. BUT when I did this to test the functionality the form submit failed because it is now doing GET instead of POST when submitting the form and endpoint is not found (I didn’t have time to dig this around this time, but will test it later and report it to Episerver support if it is an issue in Episerver implementation and not in my code).

3 thoughts on “Create custom Episerver Forms container

  1. Thanks a lot for your posts on Episerver forms! Thourough and full of the details I needed, really helpful.
    I used your tutorial to create a custom container allowing two columns, by adding an extra element area. Most of it works as intended, but I got a 500 respons when submitting the form, with the main message “EPiServerException: ContentReference: Input string was not in a correct format.]” I also have two custom elements in the container, but none of them with changes of block, controller or view, Is this something you have come across before and might have ideas about?

    1. Hi Anna, I haven’t encountered the issue you describe.

      But if you look in to the HTML source of the form there should be a hidden input called ‘__FormHostedPage’ and that has the “ContentReference” value of the page, like id 115. So that might be something that is not right currently (the string value cannot be parsed to ContentReference maybe, somethign has changed that value?)

      If you remove your custom elements from the container and submit, does it then work? If yes, then you know the issue is with your own custom elements and you should look into those, one of them is using ContentReference type property?

      What is the version of Episerver Forms you are using? There were some bugs in the version 4.24.3 (I also tested my sample for this post with the version 4.24.3 and it worked without issues) but version 4.25.0 is now released, so you might want to upgrade to that version (tested the original sample with this version too and it works).

      1. Thanks a lot for your answer. I tried to update to 4.25 and I also have a form without custom elements. I’ve forwarded the issue to Episerver who are looking into it right now. When I’ve reach a solution I will post it here.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s