Customizing WFFM in Sitecore 8
Recently I was working on a Sitecore 8 implementation where we were using WFFM for forms and Foundation to be our responsive framework. When we started working with WFFM to build our forms, we quickly ran into issues. The HTML emitted by WFFM didn’t really match our CSS classes very well, and was incompatible with Foundation. This seems to be a common problem with WFFM.
There are a number of good articles written about styling WFFM, and we initially tried to follow some of the recommendations in these articles. Our CSS was built around much simpler HTML than the HTML emitted by WFFM. Trying to get this to work correctly created a number of headaches for us.
The business requirements specified a fully responsive implementation of the site, including all forms on the site. There really wasn’t a good way do get the HTML from WFFM to play nicely with Foundation. This was a major problem, and it convinced us that we needed to customize the HTML generated by WFFM.
Whenever we customize any part of Sitecore or Sitecore modules, we always try to understand what kinds of support problems we are creating when it is time to upgrade to a new version of Sitecore or the module. Ideally, we want our custom implementation to enhance the existing functionality instead of replacing the it.
In our implementation, we are using the latest version of WFFM and Sitecore 8. The site is being implemented using MVC, so we are also using the MVC version of WFFM. It turns out that this made our customization process much easier then I thought it would be.
The default WFFM controller rendering builds a model of the type FormModel passes this to a view called Index. Since the controller is called FormController, one of the places MVC looks for the view is /Views/Form/Index.cshtml. Looking at this file, I quickly discovered that WFFM is using MVC Editor Templates to generate all the HTML.
All sites built at Hedgehog Development are designed as if we are building a multi-site implementation. This solves many problems down the road when someone wants to add additional sites to the instance of Sitecore. To help isolate our website from other sites, we use the BrainJocks MVC Areas module. Because of how MVC resolves Editor Templates, having the WFFM rendering in our area allows us to replace/create our own MVC Editor Templates for the FormModel. This prevents our changes from interfering with other sites or the default implementation of WFFM.
Creating the custom rendering
Creating a custom rendering for WFFM was relatively easy. I just copied the default rendering into our rendering folder. The placeholder settings for our pages were updated to allow the new rendering to be added instead of the default WFFM one.
Creating custom MVC Editor Templates
Creating the custom templates was a bit more difficult. There were a few steps required to get an existing form to render correctly.
First, I duplicated the index.cshtml and the web.config installed by WFFM into the /Areas/[area name]/Views/Form folder.
Next I added an EditorTemplates folder under new Form folder and started moving the templates from WFFM into my folder. The three main templates for a form are FormModel.cshtml, SectionModel.cshtml and FieldModel.cshtml. These needed to be customized to generate the correct HTML for Foundation.
Documenting all of the functions called in the .cshtml pages would take up too much time and space. To make things simple, I preserved almost all of the C# code, and replaced the default HTML with the HTML we needed for foundation. The FormModel.cshtml template is the most complex, because it contains all of the support/validation logic for the form. Be careful changing/removing this functionality, since it make break something. FormModel.cshtml also renders the sections by rendering the sections Editor Template .
The SectionModel.cshtml template was very simple to override, since it only renders the sections and then renders the fields using the field Editor Template. The HTML in this file was replaced with what we needed.
The FieldModel.cshtml template was a bit more difficult. We needed to determine how validation errors were handled and figure out how/where labels were going to be rendered. We changed the HTML for this Editor Template and we were able to view some of our forms. The forms were emitting the correct HTML for Foundation and were now responsive.
All other Editor Templates were moved over as needed and updated to use the components in foundation instead of their default renderings. This completed our customization of WFFM for Foundation.
Once everything was moved into our custom area, a problem was discovered. Existing forms worked great, but when the WFFM rendering is added to a page, a wizard dialog should be opened and the user is walked through the process of initializing the rendering. This wasn’t working. After some investigation, it was determined that this process is handled by the Sitecore.Form.Core.Pipeline.InsertRenderings.Processors.GetDialogUrl step in the getRenderingDatasource pipeline. The pipeline is executed when a rendering is added to a page. The WFFM custom pipeline steps checks to see if the ID of the rendering matches the WFFM rendering and opens the Forms.InsertFormWizard dialog.
Sometimes, it seems like Sitecore has a setting for everything. Unfortunately, in this case, it doesn’t have a setting for customizing the ID of the rendering the pipeline step is watching for. The ID of the WFFM rendering is hard coded into the pipeline step. To get around this issue, I de-compiled the WFFM step and changed it to look for the ID of our new area specific rendering. I added this step to the getRenderingDatasource pipeline before the default WFFM step, which lets me open the wizard without changing the default WFFM functionality.
I have tried this technique on Sitecore 8 Update 3,4 & 5. Since we haven’t completed the implementation for this site yet, there may still be some problems with this modification. Overall, it seems like a reasonable thing to do since I’m not changing any of the default functionality of WFFM. Since all changes are localized to our implementation, WFFM can be customized for other sites in this instance of Sitecore without fear of breaking existing functionality. The biggest risk going forward is that Sitecore completely changes the way WFFM works in the future. I suspect the chances of this is relatively low, since the WFFM implementation for MVC is relatively new. The getRenderingDatasource pipeline step is a smaller risk, and needs to be revisited if the version of WFFM is changed.