Sitecore 8.1 WFFM with MVC: Insert Form in Content Editor

In the latest versions of Sitecore, the trend is more and more to use MVC. So having an MVC project, built on Sitecore XP 8.1 rev.151003 (Initial Release) version, and wanting to use the Web Forms For Marketers module, version 8.1 rev. 151008, entails that we want to use the MVC Form rendering, instead of the classic Form sublayout. For a developer, this works perfectly well, but as a Content Editor, I encountered the issue that I could not select any placeholders in the Insert Form wizard. At first, I thought that the explanation for my issue is the same as the one in this article: http://blogs.perficient.com/microsoft/2014/04/web-forms-for-marketers-mvc-and-the-sitecore-page-editor/. It mainly has to do with the fact that in the Insert Form wizard, you will need to select the placeholder on which to add the form, but the list of placeholders cannot be created by Sitecore, because it scans the current page looking for sc:Placeholder controls, which are no longer used in MVC. But later on, I found out that this is not the case for my solution. In my case, there was a custom pipeline HttpRequestProcessor that interfered with the Insert Form wizard, so I found a workaround without changing the code from the custom pipeline.

The scenario is this:

1.) First, you open the Insert Form wizard:InsertForm

2.) Enter a name for the form, and click on either Create a blank form or Select a form to copy:

InsertFormWizard

3.) In the Select a Placeholder screen, you have to select something, otherwise, you cannot proceed to the next step. But in this case, instead of the placeholder list you would expect, the current item url is loaded inside the small wizard, which is a showstopper.

The solution to this problem begins with identifying where the request for placeholders is performed. This is done in a javascript file installed with the WFFM module: <website>\sitecore\shell\Applications\Modules\Web Forms for Marketers\script\Sitecore.PlaceholderManager.js. In the getPlaceholders function, we need to replace the Ajax request to the current url with an Ajax request to our own implementation of displaying the placeholder list. For this, we need a new very simple controller and a view in our project:

Controllers/MvcFormController.cs

public class MvcFormController : Controller
{       
    [HttpGet]
    public ActionResult Index()
    {
        return this.View();
    }
}

Views/MvcForm/Index.cshtml

<a id="ph_wffm" href="#" class="scPalettePlaceholder" title="wffm" onclick="Sitecore.PlaceholderManager.onPlaceholderClick(this, event, 'wffm');">
    <div class="scPalettePlaceholderTitle">wffm</div>
    <div class="scPalettePlaceholderTooltip" style="display: none">wffm</div>
</a>

In my case, I only need a single placeholder called ”wffm”. This was previously added in Sitecore, under Placeholder Settings:

RestrictingPlaceholdersScreen

Of course the logic can be taken even further, so that the placeholder list is retrieved dynamically. But in my case, this solution was good enough.

In the Sitecore.PlaceholderManager.js file, in the getPlaceholders function, we can adjust the Ajax request to our action:

this.getPlaceholders = function (url, success, failure) {
    if (url != null && url != '') {
        new Ajax.Request('/api/sitecore/MvcForm/Index', {
            method: 'get',
            asynchronous: false,
            onSuccess: function (transport) {
                success(transport.responseText);
            },
            onFailure: function (transport) {
                failure(null);
            }
        });
    }
    else {
        failure(null);
    }
}

Now, when I perform again the steps from my scenario, I can see the following screen for selecting the placeholder:

SelectPlaceholder

Remember to properly clear the cache of your browser before trying the scenario, so that you make sure that the changes in javascript are taken into consideration.

Custom MVC Controls for WFFM in Sitecore 8.1

The Web Forms For Marketers module is quite customizable, and the styling of the form controls would normally be manipulated from CSS classes, but I found myself in the situation where I had to adjust not only the styles of the controls, but also the html that renders behind. In this case, I investigated how to create my own custom controls and integrate them with the rest of the WFFM module. My project was built on Sitecore XP 8.1 rev.151003 (Initial Release) version, using the WFFM module, version 8.1 rev. 151008. The purpose is to customize a Single-Line Text control so that the field is surrounded by a <div> with a certain CSS class, has a label with a (*) if the field is required, and has some information displayed if filled in by the editor. The same process can then be followed in order to customize any other form control.

The first step is to check how the classic Single-Line Text control is created, and we can start by looking at the code behind. This information can be retrieved from the corresponding item in Sitecore:

SingleLineText

Our custom control will use the same class as the original control, so we do not need to change anything in the ”Assembly” and ”Class” fields. What we are interested to change is the ”MVC Type” used by our control, because we will implement a new rendering and we will need to link it in this field. Using a decompiling tool, we can see how the view model class of this control is implemented in the SingleLineTextField class (namespace Sitecore.Forms.Mvc.ViewModels.Fields, Sitecore.Forms.Mvc.dll). For most of the controls, the view model class has a strong relation with the view containing the actual control rendering, by having the same name (so naming convention is very important, as with everything in MVC). The views, as installed with the WFFM module, can be found in <website>\Views\Form\EditorTemplates. All the view model classes in the namespace Sitecore.Forms.Mvc.ViewModels.Fields inherit from FieldViewModel class (Sitecore.Forms.Mvc.ViewModels). If the view model of a control has a corresponding view with the same name, it will render that one, otherwise it will render the view of the FieldViewModel (implemented in <website>\Views\Form\EditorTemplates\FieldViewModel.cshtml). For example, the view model for the CheckboxField will render the view CheckboxField.cshtml, whereas the view model for SingleLineTextField will render the view FieldViewModel.cshtml.

So let’s create a new view in our project in the same folder as the other WFFM views, and call it MySingleLineTextField.cshtml. This will contain our code for the custom Single-Line Text rendering, and will reference a new view model with the same name. We will add a new ViewModels folder in our project and add the new class MySingleLineTextField.cs there. If we look at the code in FieldViewModel.cshtml, we can see that it makes use of the Html.BeginField() statement, which renders some tags and classes that I want removed and replaced with a different html structure. By removing this code, we need to make sure that we properly manage the label and the validation display. The advantage is that we can completely control how everything will look like by arranging the html and inserting our own CSS classes.

Views/Form/EditorTemplates/MySingleLineTextField.cshtml

@using Sitecore.Forms.Mvc.Html
@using MyProject.ViewModels
@model MySingleLineTextField

<div class="field">
    <label>
        @Html.BootstrapText("Title")
        @if (Model.IsRequired)
        {
            <abbr class="required" title="Required field">*</abbr>
        }
    </label>
    @Html.BootstrapEditor("Value", new string[] { "input-text" })
    @if (!string.IsNullOrEmpty(Model.Information))
    {
        <p class="small-note">
            @Html.BootstrapText("Information")
        </p>
    }
    <p class="small-note">
        @Html.BootstrapValidationMessage("Value")
    </p>
</div>

ViewModels/MySingleLineTextField.cs

using Sitecore.Forms.Mvc.ViewModels.Fields;

namespace MyProject.ViewModels
{
    public class MySingleLineTextField : SingleLineTextField
    {
        public MySingleLineTextField()
        {
        }       

        public override void Initialize()
        {
            base.Initialize();       
        }
    }
}

Now we can create the custom field in Sitecore and link it with the custom rendering. It is easier to copy the existing ”Single-Line Text” item and rename it. We will add the new item under a ”Custom” folder:

MySingleLineText

The custom field can be added on a new or existing form, like in the screenshot below:

CustomFieldOnForm

As a conclusion, we could create variations for any of the existing form controls, customizing the rendering in any way we want, provided that we also implement a view model class with the same name as the rendering. In order to know what to write in the view model class, just look at the decompiled version of the original view model from the Sitecore.Forms.Mvc.dll.