Web Forms for Marketers (WFFM) ‒ Part 1 ‒ Custom Radio List Field ‒ Data source and Appearance


One of the most powerful Modules in Sitecore is Web Forms for Marketers.
The most powerful forms engine I ever saw!

Installing is quite easy, configuring has some tripping hazard (feel free to contact me, to solve your problems setting up WFFM), but if everything runs as expected you will love it!

I have never, never, never ever build such complex forms without coding!

But stop, sometimes advertising agencies have great designs and great ideas which looks beautiful…. in Photoshop

As a developer, you can despair sometimes on templates you get as a requirement, because for sure the customer likes the well designed templates for his page. 🙂

And sometimes, also WFFM has its limits realizing such templates from Page Editor.

So far so good, here is a scenario, where Design meets coding… where Photoshop meets me :D, because I’m a coding designer and I love to realize such challenges in Sitecore 😉

Okay, enough talking, here we go:

Scenario: The customer has Seminars with any number of appointments, the seminars can have a start date, an end date, a location, a information text and, that’s important later, a fix number of seats.

Structure in Sitecore looks like this:

01_structure_in_sitecore

Visitors can fill out a form to register to a seminar, in fact that data should be saved to Database, one Mail should be send to the registrant, one Mail should be send to the customer and a custom Save Action should count down the available seats, I do that in WFFM!

Here is the template how the form should look like:

SeminarsForm

Well, uuuuuhm… nice one … everything is fine and can build by the form designer, except the appointment Radio List above.

There are 2 difficulties to take care about.

  1. WFFM can select items for a Radio List from the tree and by queries. But I want to display the children of the current context item. It took a long time for me to realize that the form doesn’t have the context item, please correct me if I ‘m wrong! Queries like: child::*[@@templateid='<Some Guid>’] works fine in XPath Builder if the path is set to a seminar item… But, start path for queries is /sitecore, you will get no result or you can use descendant::*[@@templateid='<Some Guid>’] and you will get all appointments… I was not able to handle that with queries 😦
  2. In case you have a result in your query… you are able to set a value and a text for the List Item (both from any fields of the item). Let’s look again at the picture above. Title comes from the Seminar itself, the other 3 lines are information from the appointment…. pah! Not possible to display that with functionality of the form designer …

It is possible to display that, even in the form designer. What we need is a new Radio List Field Type and of course what we do next is very specific, and we only need this to display the Seminars Radio List, so we call our new Control SeminarsRadioList, which inherits from Sitecore.Form.Web.UI.Controls.ListControl.

I don’t want to get in deep so I’ll show you just the method to override, and the methods I need to display the text as required in combination with Glass.Mapper. If you are not conform with Glass.Mapper do the following:

  • override InitItems()-Method
  • in InitItems get the context item (the seminar)
  • Create a new method to iterate through the children (appointments) where the available seats greater 0 (in part 3 we count down the seats for each registration as a custom save action!)
  • return a new ListItemCollection, each List Item has a Text and a Value, format the Text as required (Method is self explainable), Value is the Id of the appointment

That’s it!

protected override void InitItems(ListItemCollection collection)
		{
			var context = new SitecoreContext();
			var seminar = context.GetCurrentItem&amp;lt;SeminarModel&amp;gt;();
			var appointmentsCollection = CreateAppointmentsListItemCollection(seminar);

			base.InitItems(appointmentsCollection);
		}

		private ListItemCollection CreateAppointmentsListItemCollection(SeminarModel seminar)
		{
			var appointments = seminar.Children.OfType&amp;lt;AppointmentModel&amp;gt;().Where(x =&amp;gt; x.AvailableSeats &amp;gt; 0);

			var collection = new ListItemCollection();
			var index = 0;
			foreach (var appointment in appointments)
			{
				collection.Add(new ListItem(GetAppointmentText(seminar.Title, appointment), appointment.Id.ToString())
				{
					Selected = index == 0
				});
				index++;
			}
			return collection;
		}

		private string GetAppointmentText(string seminarTitle, AppointmentModel appointment)
		{
			var text = string.Format("{0}<br/>{1}<br/>{2}<br/>{3}", seminarTitle, appointment.DateTimeFrom, appointment.Location, appointment.InfoText);
			return text;
		}

The result looks like this:

AppointmentInRadioList

Great, isn’t it? Next step I tried is to check if WFFM recognize my little hook. 🙂

I set of course a “Send Email Message” Save Action to have a look how the fields are rendered in the mail.

But after submit there was only a Guid in the mail of course the Id of the appointment which was set as value of the List Item…

During installation and configuring WFFM I read about a custom pipeline:
How to Configure an Email Message Using the ProcessMessage Pipeline (Page 41 in WFFM Reference)

Following that example, you will be able to get the Seminars Radio List field:

var seminarsField = args.Fields.FirstOrDefault(x =&gt; x.FieldID == FieldIds.Forms.SeminarRegistration.Seminars); //constant Guid to the seminars field ID
if (seminarsField != null)
{
	args.Mail.Insert(0, seminarsField.Parameters);
}

My first thought was: Cool I have the value (Guid) of the appointment, I could take the Guid, fetch the item again and format the mail. But it was easier as expected! In seminarsField.Parameters is exactly the text we formatted in the picture above!!!

The Email looks like this:

email

All information are present. 🙂

In the next step to finish the form I challenge the other difficulty… dynamically show/hide fields WFFM… 😉

Stay tuned!

Best regards Dirk

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.