Creating a custom action editor for WFFM

Posted 10/21/2013 by mschultz

Recently, I needed to write a simple editor for a custom Web Forms For Marketers (WFFM) action. Not having done this lately, I went about it in the usual way. I fired up reflector (actually it was already running) and started browsing the WFFM dlls. Sitecore.Forms.Core.dll and Sitecore.Forms.Custom.dll are the main ones.

At first, I was a little confused. Most of the editors were Xaml and extended a special base class EditorBase or an even more special base class XamlIDEHTMLEditorForm. Surely I didn't need all that functionality to add a simple parameter to my action. As it turns out, I was right. The only thing the editor needs to be able to do is set it's return value to a valid parameters string for the action.

For this example, I'm going to show a minimal "hello world" type example, but this can be extended to almost anything you might need to initialize an action with. For our minimal example, I'll create an editor that lets you select an item from the content tree to pass to your action.

First let's create a new save action. Actions are located in

"/sitecore/system/Modules/Web Forms for Marketers/Settings/Actions/Save Actions"

Right click on save actions and create a new one. I'm calling mine Test Save Action.

There are three fields that we're interested in for our save action; assembly, class and editor. The first two are fairly common in sitecore and specify the assembly and class to find our new action in. Our action should extend BaseSaveAction and implement the Execute method. Here's the skeleton for our TestSaveAction class.


using Sitecore.Data;

using Sitecore.Form.Core.Submit;
using Sitecore.Form.Core.Configuration;
using Sitecore.Form.Core.Client.Data.Submit;

namespace NTTData.Forms.Submit
{
    public class TestSaveAction : BaseSaveAction
    {

        public override void Execute(ID formid, AdaptedResultList fields, params object[] data)
        {
	
        }
	
        public string TestItemID 
        {
			get;
			set;
        }
    }
}

So given this skeleton, the assembly and class for our save action should look something like

FieldValue
AssemblyTestSaveAction.dll
ClassNTTData.Forms.Submit.TestSaveAction

WFFM has a neat feature in that if you set up a parameter in your action you can automatically use it by declaring a public property of the same name. So TestItemID will be the name of the parameter that we create for our action and will be automatically populated when we successfully set the parameter via our action editor.

Now for the fun part, creating the editor. For this example, I'm going to use the xml control format. However, you could also use Xaml or even a custom web form to populate your action parameter as long as you follow the parameters format. First let's set the editor field to the control we want to use

FieldValue
Editorcontrol:Form.SelectItem

Here's the source code for my test editor.


using System;
using Sitecore.Web.UI.Pages;
using Sitecore.Data.Items;
using Sitecore.Web.UI.Sheer;
using Sitecore.Web.UI.XmlControls;
using Sitecore.Web.UI.HtmlControls;
using System.Collections.Specialized;
using Sitecore.Form.Core.Utility;

namespace NTTData.Forms.Dialogs
{
    class SelectItem : DialogForm
    {
        protected GenericControl CurrentPlaceholder;
        protected XmlControl Dialog;
        protected DataContext ItemDataContext;
        protected DataTreeview ItemTreeView;
		
        protected NameValueCollection nvc = new NameValueCollection();

        public string Params
        {
            get
            {
                return (System.Web.HttpContext.Current.Session[Sitecore.Web.WebUtil.GetQueryString("params")] as string);
            }
        }

        protected override void OnLoad(EventArgs e)
        {

            base.OnLoad(e);

            if (!Sitecore.Context.ClientPage.IsEvent)
            {
                this.Localize();
                
                nvc = ParametersUtil.XmlToNameValueCollection(Params);
                
                TestItemID = nvc["TestItemID"];

                if (!string.IsNullOrEmpty(this.TestItemID) && Sitecore.Data.ID.IsID(this.TestItemID))
                {
                    this.ItemDataContext.DefaultItem = this.TestItemID;
                }
                this.OnNodeSelected(this, EventArgs.Empty);
            }
            this.ItemTreeView.OnClick += new EventHandler(this.OnNodeSelected);
        }

        private void OnNodeSelected(object sender, EventArgs e)
        {
            if (this.ItemDataContext.CurrentItem != null)
            {
                string str = this.ItemDataContext.CurrentItem.ID.ToString();
                nvc.Add("TestItemID",str);
            }
        }

        protected override void OnOK(object sender, EventArgs args)
        {
            Item selectionItem = this.ItemTreeView.GetSelectionItem();
            if (selectionItem == null)
            {
                SheerResponse.Alert("Choose an item", new string[0]);
            }
            else
            {
                nvc.Add("TestItemID", selectionItem.ID.ToString());
                string str = ParametersUtil.NameValueCollectionToXml(nvc);
                if(str.Length==0)
                {
                    str="-";
                }
                SheerResponse.SetDialogValue(str);
                base.OnOK(sender, args);
            }
        }

        public string TestItemID { get; set; }
    }
}

The above code is a simple dialog with a tree list widget in it to select an item from the Sitecore content tree. A full explanation of this code is out of scope, but I will point out the features relevant to WFFM.

First, the Params property provides the existing value for the action, so that if you've already set it your value is available to the editor. It will also give you default values when newly created if you have them set in your action. A field that we didn't talk about on the action item is Parameters. You can set this to an xml string and WFFM will pass those in as parameters when the action is first created.

Sitecore provides a utility class to help you format your parameters for WFFM called ParametersUtil. We use the ParametersUtil to go to and from Xml and NameValueCollection.

The magic that lets you set the parameters of your action happens in the OnOK method. All we need to do is format our parameters using ParametersUtil and call SetDialogValue on the result. The xml control below completes the example and goes with the SelectItem class. Remember you need to add it in a directory that's listed in controlSources section of Sitecore's configuration. That's all there is to it. Have fun creating your custom WFFM action editors and remember if you have any questions or comments, you can contact me at matthew dot schultz at nttdata dot com.


<?xml version="1.0" encoding="utf-8" ?>
<control xmlns:def="Definition" xmlns="http://schemas.sitecore.net/Visual-Studio-Intellisense" xmlns:content="http://www.sitecore.net/content">

  <Form.SelectItem>
  
    <FormDialog ID="Dialog" Icon="Applications/32x32/window.png">

      <Script runat="server" Src="/sitecore/shell/controls/Sitecore.js"/>
      
      <Script runat="server" Src="/sitecore/shell/controls/SitecoreObjects.js"/>

      <Script runat="server" Src="/sitecore/shell/controls/SitecoreModifiedHandling.js"/>

      <Script runat="server" Src="/sitecore/shell/Controls/Sitecore.Runtime.js"/>

      <Stylesheet Src="FormBuilder.css" DeviceDependant="true"/>

      <CodeBeside Type="NTTData.Forms.Dialogs.SelectItem, TestSaveAction"/>
      
      <GridPanel Width="100%" Height="100%" vAlign="top">

        <DataContext   ID="ItemDataContext" DataViewName="Master" ShowRoot="false" />

        <GridPanel Width="100%" Height="100%" GridPanel.Height="100%">

          <GridPanel  Columns="1" Width="100%" Height="100%" Fixed="true" Border="1px inset"  GridPanel.Height="90%" >

            <Scrollbox GridPanel.vAlign="top" Padding="10 10 10 10" Width="100%"  Height="100%" Background="window" Border="none" Style="filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=1, StartColorStr='#ffffff', EndColorStr='#DFE6EC')" GridPanel.ID="FoldersPane" GridPanel.Width="100%">

              <DataTreeview Width="100%" ID="ItemTreeView" DataContext="ItemDataContext" AllowDragging="false" />

            </Scrollbox>

          </GridPanel>

        </GridPanel>

      </GridPanel>
      
    </FormDialog>

  </Form.SelectItem>


</control>

Share:

Archive

Syndication