WFFM Custom Field Type made easy!

Anyone who has used the Sitecore module “Web Forms for Marketers” knows that although the module is absolutely the coolest thing ever to let marketing people create all their own forms, if you’re a developer and you need to make a form that has a form field with any bit of back-end logic to it, there’s just no way to do any of that with the out of the box form fields.  There is some excellent documentation out on the SDN for creating custom user fields.. however, it’s not complete in that there are 2 types of forms fields – A User control field type (basically an ascx type of file) and a Web Control that you would create from scratch.  The documentation covers creating the web control type of field.  However, I think most people would find it much more useful to create a simple ascx type file to extend a normal field type to allow for back-end business logic to be performed.  This is my purpose for this post.

So basically what I was needing was to be able to take a drop down list, populate it with Sitecore type data..which you can do.. except that this data required a complex query to filter items.. and then the items needed to be sorted.  Sitecore query handles that query very well.  Anyone who has built a template has gotten familiar with this and the module handles that quite well.  The problem is that there just isn’t any way to put an inline command for sorting and WFFM doesn’t have any out of the box way to sort data dynamically generated date in the drop down field type.

The thing to realize is that user control field types really are just a basic user control that extends the WFFM base user control – Sitecore.Form.Web.UI.Controls.BaseUserControl.  Also, in order to use the “Title” that is specified in the form designer, you’ll need to implement the  Sitecore.Form.Web.UI.Controls.IHasTitle interface.

Oh and lemme add this because you’ll need it for the sorting:


public class SimpleComparer : Comparer

{<br />
   // This just compares the items and sorts them by their name.<br />
   protected override int DoCompare(Item item1, Item item2)

   {<br />
      string x = item1.Name;<br />
      string y = item2.Name;<br />
      return x.CompareTo(y);<br />
   }<br />
}</p></pre>

This is easy enough to do.. but since it took me a bit to sort through the WFFM assembly to find out what it was doing, I’ll save you guys some of the trouble.   I tried this in a 6.5 instance with WFFM 2.3 and my control worked beautifully.   Basically your control needs to inherit a few classes and then create your control like you would any other control. And no comments about my choice of coding techniques! I don’t care.. that’s not my point.


    // The control must inherit either &quot;BaseUserControl&quot; for user controls or &quot;BaseControl&quot; for web controls.  I also<br />
    // implement the IHasTitle interface to allow the user to set the title for the field in the form designer diaglog.

    public partial class CustomFormDropdown : Sitecore.Form.Web.UI.Controls.BaseUserControl, Sitecore.Form.Web.UI.Controls.IHasTitle

    {<br />
        // This sets the value of the label to be the value set by the user in the form designer.<br />
        public string Title<br />
        {<br />
            get<br />
            {<br />
                return this.DropLabel.Text;<br />
            }<br />
            set<br />
            {<br />
                this.DropLabel.Text = value;<br />
            }<br />
        }</p></pre>
protected void Page_Load(object sender, EventArgs e)
<pre>
        {<br />
            //create my collection of Sitecore items with a Sitecore query.  This can be done however works best for you.<br />
            //This list, actually, is collecting all the Workflow action items.. for no other reason than that I didn't want to bother creating it<br />
            List selectionItems = new List();

            selectionItems.AddRange(Sitecore.Context.Database.SelectItems(&quot;/sitecore/system/Workflows//*[@@templatename='Command']&quot;));</p></pre>
//Sending item collection off to a comparer class.
<pre>
            SimpleComparer com = new SimpleComparer();

            selectionItems.Sort(com);</p>
<p>            //binding the data to my drop down list item.<br />
            ActionTitle.DataSource = selectionItems;<br />
            ActionTitle.DataValueField = &quot;ID&quot;;<br />
            ActionTitle.DataTextField = &quot;Name&quot;;<br />
            ActionTitle.DataBind();<br />
            ControlContainer.CssClass = this.CssClass;<br />
        }</p></pre>

Now that you have created your user control, the last step is to implement the code that WFFM will need to be able to get the value from our form field. You can also implement some of our custom properties as well. Depending on what you put in this area, you can add additional fields to your form designer.

</p>
<p>        // Properties that are added by the form designer.  These are purely optional and are here to show you that you can do this if you want<br />
        // Notice there are properties such as "DefaultValue" that can be left blank.

        [VisualProperty("Css Class:", 600), DefaultValue ("scfDroplistBorder"), VisualFieldType(typeof(CssClassField))]

        public string CssClass { get; set; }</pre>
&nbsp;
<pre>
<p>        // Properties<br />
        [VisualProperty("Help:", 500), VisualFieldType(typeof(TextAreaField)), Localize, VisualCategory("Appearance")]

        public string Information { get; set; }</p></pre>
// Take note!!  This is the mucho important part!!!
<pre>
        // This is required by WFFM to get the value from the drop down when the user submits the form.

        // This is all the code you need!<br />
        public override Sitecore.Form.Core.Controls.Data.ControlResult Result<br />
        {<br />
            get<br />
            {<br />
                //ControlName is automatically set by WFFM.  Don't set this.

                //The second part is for a string to represent the value of your drop down.<br />
                //The 3rd one is for optional parameters and is completely optional.

                return new Sitecore.Form.Core.Controls.Data.ControlResult(this.ControlName, this.ActionTitle.SelectedValue, null);<br />
            }<br />
        }<br />

Here’s my simple html ascx page.

<p>
<asp:Panel ID="ControlContainer" runat="server">
  <asp:Label ID="DropLabel" runat="server" CssClass="scfDropListLabel" AssociatedControlID="ActionTitle" />
  <asp:Panel ID="DropDownPanel" CssClass="scfDropListGeneralPanel" runat="server">
    <asp:<span class="hiddenSpellError">DropDownList runat="server" id="ActionTitle" CssClass="scDropList" />
    <asp:Label ID="dropDownHelp" Style="display:none" runat="server" />
  </asp:Panel>
</asp:Panel>
<br />
</p>


Now as I said, there were some optional fields that you can set up to show in the form designer. If you don’t do that.. then your form field will have no fields other than the title and analytics which is handled within Sitecore anyway. Once you have your user control saved, go into the /sitecore/Settings/Modules/Web Forms for Marketers/Settings/Field Types/Custom , create a new item using the Field Type template. Then down in the “code” area of the item, put in the link to your control “/controls/CustomFormDropdown.ascx” (without the quotes).

Now, when you create or edit forms, you’ll have your new user control available and it should return its value without incident and you now have a snazzy new form field type for future use.

Please let me know if I’m forgetting anything here..

5 thoughts on “WFFM Custom Field Type made easy!

  1. It’s fixed. I had some issues with WordPress and the code that is supposed to generate source code when I switched my theme. I had to redo most of them by hand. I missed that last text box. Thank you!

    Like

  2. Any idea how to create a field that has validation attached to it? If I inherit the ValidateUserControl class and override the ValidatorContainer properties I get an error that looks something like: Unable to find control id ‘field_A5FA4CC6E0A3490AA8699E51F1765492’ referenced by the ‘ControlToValidate’ property of ‘field_A5FA4CC6E0A3490AA8699E51F17654928937C6DD55554D86B126816635E96167_validator’

    Like

  3. Hi,
    Good and helpful article. I have a task to create a 2 dropdown lists and populate first on load and second on first selected using JSON web service. All looks good and selection is working good. My problem is on submit action second list is always empty and I cannot get selected value from second list.
    Do you have any tip how to solve that?

    Like

Leave a comment