Is there a way in EE to disable the code syntax highlighting?

Freeform + FieldFrame = ExpressionEngine Form Builder

A form builder is a regular request for some clients when they are looking for a content management system. There aren’t that many CMS that have this kind of functionality built-in, and even if they do, the implementation is usually less than desirable.

If you follow along with what I’ve been up to, you can probably tell that I have been on a big ExpressionEngine kick. I’ve been using it on a ton of projects recently, and I love it for its flexibility. Although it does lack a true form builder, I figured out a simple way to build one.

If you are impatient and just want to get to the demo, go ahead. Although the form will look like nothing special, as I have just added some simple styling. The real magic of the form builder happens in the Control Panel.

We Need Add-ons

This form builder would not be possible without the use of some awesome add-ons:

  • FieldFrame

    This one is a no-brainer. I can’t even imagine building a site without it.

  • Freeform

    If you need a form in EE, this is the way to do it.

  • Freeform Data Select

    A new fieldtype which pulls in templates and fields from the Freeform module.

Creating a Field Group

I built a custom Field Group called Forms, which consisted of four fields:

  • Template
  • Notification Email Addresses
  • Return Page
  • Fields

The first three are pretty simple, so I will just give a quick run through on the specifications for those fields and give a more detail review of the Fields field:

Template

This is where you select the Freeform template that will be used for the email. This field is not completely necessary, as just using the default template should be good enough, but I figured since it was an option, to throw it in.

  • Field Name: form_template
  • Field Type: Freeform Data Select
  • Populate drop-down with: Freeform Templates

Notification Email Addresses

This is where you will enter the email address(es) that you want to email when the form is submitted. Since Freeform wants multiple email addresses separated by the | character, I added some help text describing that as well.

  • Field Name: form_notify
  • Field Type: Text Input
  • Default Text Formatting for This Field: None
  • Hide Formatting Menu

Return Page

This is where you enter the URL to the thank you page. Once a user successfully submits the form, they will be redirected here.

  • Field Name: form_return
  • Field Type: Text Input
  • Default Text Formatting for This Field: None
  • Hide Formatting Menu

Fields

This is where the magic happens. This field is a FF Matrix field type that consists of five other fields. Each row of the FF Matrix represents one field (or field group) in the form. I’ll give a brief description of each field of the FF Matrix and show you a screenshot so you can get a better picture:

  • Field Name: form_field
  • Field Type: FF Matrix

Label

This is where you will enter the label for the form field:

  • Col Name: label
  • Cell Type: Text Input

Field

This field pulls in all of the fields that have been entered into the Freeform module. So you are presented with a dropdown of all of the fields, and you just select the appropriate one:

  • Col Name: field
  • Cell Type: Freeform Data Select
  • Populate drop-down with: Freeform fields

Field Type

This is where you select the type of form field you want to use. I put in a few different options, but this could be expanded upon too:

  • Col Name: type
  • Cell Type: FF Select
  • Select Options: Text Input
    Textarea
    Select
    Multi-select
    Checkbox
    Checkbox Group
    Radio Group

Is this field required?

With most forms, there are some fields that are required and some that are not. If you want the field to be required, you just check the checkbox and the Freeform module will make sure it is filled in:

  • Col Name: required
  • Cell Type: FF Checkbox
  • Checkbox Label: Is this field required?

Options

Finally, this field is used when you select a field type that has multiple options. For example, if you select a “Select” field type, you need to provide the options to populate it. So you enter the options separated by the | character:

  • Col Name: options
  • Cell Type: Text Input

FieldFrame Matrix Configuration

So that is all you need for the Field Group, now go ahead and create a Forms Channel (or Weblog) and make sure to assign the Forms Field Group to it.

Now, when you go to publish a Forms entry, you should see something like this:

New Forms Entry

I made a demo form showing off the various types of form fields. Here is what that entry looks like in the Control Panel:

Demo Form Entry in Control Panel

Template

Now that we have our Channel and Field Group all setup, we need to deal with the template. You could really setup your template/template group in various ways, so I’m not going to get into those details. One detail that you need to know is that I enabled PHP for my template.

First, we just need to start with a simple exp:weblog:entries tag:

{exp:weblog:entries weblog="forms" limit="1" disable="categories|category_fields|member_data|pagination|trackbacks"}
…
{/exp:weblog:entries}

Next, we want to start the Freeform form tag:

{exp:weblog:entries weblog="forms" limit="1" disable="categories|category_fields|member_data|pagination|trackbacks"}
	{exp:freeform:form form_name="{url_title}" form_id="{url_title}" template="{form_template}" notify="{form_notify}" return="{form_return}"}
	…
	{/exp:freeform:form}
{/exp:weblog:entries}

Since we are inside of the exp:weblog:entries tag, we have access to everything that is being returned from that entry. If you have any questions about the various parameters, refer to the Freeform Documentation.

So far, the values that we are passing into the parameters are pretty straightforward, just custom fields from our entry. But, passing in the required parameter is a little more challenging, since we have to loop through all of the rows in our FF Matrix.

If we refer to the FF Matrix documentation, we can see how to loop through the rows in the matrix. I only want to return rows that have the required checkbox checked, and I want to separate the names of the fields with the | character. Then, I use the backspace parameter to remove the last one:

{exp:freeform:form form_name="{url_title}" form_id="{url_title}" template="{form_template}" notify="{form_notify}" return="{form_return}" required="{form_field search:required='y' backspace='1'}{field}|{/form_field}"}
…
{/exp:freeform:form}

Next, we want to add a title, ordered list that will contain the form fields, and the submit button:

{exp:freeform:form form_name="{url_title}" form_id="{url_title}" template="{form_template}" notify="{form_notify}" return="{form_return}" required="{form_field search:required='y' backspace='1'}{field}|{/form_field}"}
	<h1>{title}</h1>
	<ol class="forms">
		…
		<li class="buttons"><input type="submit" name="submit" value="submit" /></li>
	</ol>
{/exp:freeform:form}

Now here is where the code gets interesting. Just like we did with the required parameter, we want to loop through each row in the FF Matrix and display a list item for each one:

{form_field}
	<li>
	…
	</li>
{/form_field}

First, let’s display the label, if there is one, and denote if the field is required or not:

{if "{label}"}
	<label for="{field}">{if "{required}" == "y"}<em class="required">*</em>{/if}{label}</label>
{/if}

The rest of the code is a big conditional statement which depends upon the Field Types that you specified in the FF Matrix. Let’s first take a look at the Text Input, Textarea, and Checkbox types since they are pretty straightforward:

{if "{type}" == "Text Input"}
	<input type="text" name="{field}" id="{field}" />
{if:elseif "{type}" == "Textarea"}
	<textarea name="{field}" id="{field}"></textarea>
{if:elseif "{type}" == "Checkbox"}
	<input type="checkbox" class="checkbox" name="{field}" id="{field}" />
…
{/if}

So we are just checking the type column in the FF Matrix, and then displaying the rest of the data from the row in the appropriate form field.

Next, let’s walk through what happens if you select the Select or Multi-select types:

{if:elseif "{type}" == "Select" || "{type}" == "Multi-select" && "{options}"}
	<select name="{field}{if "{type}" == "Multi-select"}[]{/if}" id="{field}"{if "{type}" == "Multi-select"} multiple="multiple" size="4"{/if}>
		<?php $items = explode("|", '{options}'); ?>
		<?php foreach ($items as $item) { ?>
			<option value="<?php echo $item; ?>"><?php echo $item; ?></option>
		<?php } ?>
	</select>
…
{/if}

So first, we are displaying the select element, and if it is a Multi-select, we are adding [] to the name attribute, and adding the multiple and size attributes.

Next, we want to take the string of options that are separated by the | character, and create an array out of the string using the explode function.

Then, we loop through the array, and display the options for each one.

Finally, we do virtually the same thing for the Radio Group and Checkbox Group field types:

{if:elseif "{type}" == "Radio Group" && "{options}"}
	<ul class="group">
		<?php $items = explode("|", '{options}'); $count = 1; ?>
		<?php foreach ($items as $item) { ?>
			<li><input type="radio" class="radio" name="{field}" id="{field}<?php echo $count; ?>" value="<?php echo $item; ?>" />
			<label for="{field}<?php echo $count; ?>"><?php echo $item; ?></label></li>
			<?php $count++; ?>
		<?php } ?>
	</ul>
{if:elseif "{type}" == "Checkbox Group" && "{options}"}
	<ul class="group">
		<?php $items = explode("|", '{options}'); $count = 1; ?>
		<?php foreach ($items as $item) { ?>
			<li><input type="checkbox" class="checkbox" name="{field}[]" id="{field}<?php echo $count; ?>" value="<?php echo $item; ?>" />
			<label for="{field}<?php echo $count; ?>"><?php echo $item; ?></label></li>
			<?php $count++; ?>
		<?php } ?>
	</ul>
{/if}

So that’s it really. Here is the full template:

{exp:weblog:entries weblog="forms" limit="1" disable="categories|category_fields|member_data|pagination|trackbacks"}

	{exp:freeform:form form_name="{url_title}" form_id="{url_title}" template="{form_template}" notify="{form_notify}" return="{form_return}" required="{form_field search:required='y' backspace='1'}{field}|{/form_field}"}

		<h1>{title}</h1>
		<ol class="forms">
			{form_field}
				<li>
					{if "{label}"}
						<label for="{field}">{if "{required}" == "y"}<em class="required">*</em>{/if}{label}</label>
					{/if}
					{if "{type}" == "Text Input"}
						<input type="text" name="{field}" id="{field}" />
					{if:elseif "{type}" == "Textarea"}
						<textarea name="{field}" id="{field}"></textarea>
					{if:elseif "{type}" == "Checkbox"}
						<input type="checkbox" class="checkbox" name="{field}" id="{field}" />
					{if:elseif "{type}" == "Select" || "{type}" == "Multi-select" && "{options}"}
						<select name="{field}{if "{type}" == "Multi-select"}[]{/if}" id="{field}"{if "{type}" == "Multi-select"} multiple="multiple" size="4"{/if}>
							<?php $items = explode("|", '{options}'); ?>
							<?php foreach ($items as $item) { ?>
								<option value="<?php echo $item; ?>"><?php echo $item; ?></option>
							<?php } ?>
						</select>
					{if:elseif "{type}" == "Radio Group" && "{options}"}
						<ul class="group">
							<?php $items = explode("|", '{options}'); $count = 1; ?>
							<?php foreach ($items as $item) { ?>
								<li><input type="radio" class="radio" name="{field}" id="{field}<?php echo $count; ?>" value="<?php echo $item; ?>" />
								<label for="{field}<?php echo $count; ?>"><?php echo $item; ?></label></li>
								<?php $count++; ?>
							<?php } ?>
						</ul>
					{if:elseif "{type}" == "Checkbox Group" && "{options}"}
						<ul class="group">
							<?php $items = explode("|", '{options}'); $count = 1; ?>
							<?php foreach ($items as $item) { ?>
								<li><input type="checkbox" class="checkbox" name="{field}[]" id="{field}<?php echo $count; ?>" value="<?php echo $item; ?>" />
								<label for="{field}<?php echo $count; ?>"><?php echo $item; ?></label></li>
								<?php $count++; ?>
							<?php } ?>
						</ul>
					{/if}
				</li>
			{/form_field}
			<li class="buttons"><input type="submit" name="submit" value="submit" /></li>
		</ol>
	{/exp:freeform:form}
{/exp:weblog:entries}

Conclusion

This is not meant to be an all-inclusive form builder, as you can see there are many other parameters for the Freeform module. But, this was meant to show a creative use of ExpressionEngine and EE add-ons to add functionality that is not directly built into the CMS.

So go forth and create.

Share This:
  • del.icio.us
  • Digg
  • Twitter
  • Facebook
  • StumbleUpon
  • Google Bookmarks
  • NewsVine
  • Technorati
  • Reddit
  • LinkedIn

RSS feed of comments for this entry

  1. Hey that’s a great idea!!
    thx for sharing will definitely try this out.

  2. Great way to think outside the box! Once again, the flexibility of EE is amazing.

  3. This is magic!

  4. Rock! Exactly why I made the Freeform Data Select fieldtype.

    Just never got around to writing a…writeup. Good work!

  5. @Tim Kelty-
    Thanks, and thanks for the fieldtype!

    I was planning on having the user just manually enter the field/template, but the fieldtype really tied it in together and made the process so much simpler.

  6. The power/flexibility of ExpressionEngine keeps surprising me, and I’ve been using it for 2 years!

    This could be useful for a couple of my sites, thanks for sharing.

  7. @Trevor-

    Thats what I was doing initially too.

    As a side note, for more complex forms where it’s harder to build the fields modularly with each field a ffmatrix row, sometimes I just have a textarea for ‘form body’ with all the form markup in there, then a ffmatrix field for required fields using freeform data select set to fields. Not as cool, but for more complex forms sometimes just easier.

  8. This is brilliant. Thanks for sharing.

  9. Great work Trevor, but there’s just one small problem that I can see: when you’re creating groups of radios or checkboxes, you’re creating a label to describe the group that’s not actually associated with an input.

    In these cases, the ‘question’ should actually be a legend and the legend and inputs all wrapped in a separate fieldset, so you’d need to add some more conditional logic to your template to cater for that situation.

  10. Thanks for the tutorial!

    I’m trying to implement this now, but for some reason Freeform Data Select isn’t showing up in my list of FieldFrames in my Extensions Manager.

    On the server, is the ‘ft.tbk_freeform_data_select.php’ file supposed to be in its own folder within the fieldtypes folder? It’s the only field type I’ve downloaded that hasn’t come in its own folder.

    Any help is greatly appreciated.

    Thanks!

  11. @John Faulds-
    Valid point. Like I said, this is just meant to be an example, I am not expecting people to just copy all my code as is.

    @Adam R-
    Yep, you have to create a tbk_freeform_data_select folder in the fieldtypes folder and then drop the PHP file in. I got tripped up on that too.

  12. @Trevor-
    Thanks, Trevor!

  13. Hi, thanks for the tutorial!
    I’m having problem viewing in my EE cp the freeform data select type to choose from, i’ve installed the extension, eventhough the file .php is inside the fieldtypes folder. Usually other fieldframe fieldtypes have their own dedicated folder.

    hope i’m clear.
    ciao

  14. @Lincoln-
    See my previous comment.

  15. This is bad ass! Thanks for sharing, it seem every week someone in the community is coming up with ingenious ways of extending ExpressionEngine.

    Nice work

  16. Got it now!, Thanks Trevor

  17. @Trevor-

    Sorry guys, dunno why I didn’t have the folder in the github repo…updated now.

  18. @Tim Kelty-
    No worries, we figured it out. Again, awesome work on the fieldtype. What would we do without FieldFrame?!

  19. Great idea Trevor.

    You’ve just found a way to give clients freedom to create their own forms.

  20. Very cool, took me a bit to really figure out what when and where but once I got that out of the way it’s a lovely thing. Way to go Trevor!

  21. Thanks for all of your help with this Trevor.

    For some reason the following code gives me a blank page:

    {if "{label}"}
    
    {/if}

    If I remove the ‘if’ statement, everything works perfectly. Any ideas why?

    It’s not really a big deal, but I was just wondering.

    Thanks!

  22. @Adam R-
    Not sure, you may need to bring that up with Brandon.

  23. Hi,
    In my trying to implement your code the {form_field} tag is not recognizing.
    What is the {form_field} parameter?

    Thanks!

  24. @Ruslan V-
    form_field is the short name for the FieldFrame matrix field.

  25. I’ve followed this great tutorial to the T, but the form is empty, not rendering and showing

    {form_field}
    {/form_field}

    above the submit button. My first thought was that PHP wasn’t enabled (and it wasn’t), but I went through the template prefs and enabled PHP for the template I’m using and still nothing.

    Any ideas? Really digging this method so I hope I can get past this bump.

  26. @Chris-
    So the actual EE code is displaying? FieldFrame is working fine on the backend? Are you on the latest version? Are you sure you named the fields the same?

  27. Appears weblog title is being generated, and submit button working. FieldFrame appears to be terrific on the back end. Latest version; yes. Named the fields the same, too.

    Perhaps a question would be for the Fields (“This is where the magic happens.”) — What did you name that custom field? And does that matter?

  28. Figured it out: I had named my custom field for the Fields “form_fields” and not “form_field” which wasn’t explicitly noted.

    I referenced freeform required call and noticed that “form_field” was the called name.

    Being new to this structure, that was a biggie to be sure I got that correct (maybe it should be noted like you did for the first 3 fields – e.g. “Field Name: form_field”).

    Thanks for the post!

  29. @Chris-
    Cool, glad you got it working.

  30. This a great tutorial and exactly what I was looking for.

    One question. I am trying to build this out with the option of two columns. I created another FF column named ff_col with two select options (Column 1 and Column 2). Instead of showing the field contents on the final render page, I have it as a condition where ff_col == “Column 1″ do this and ff_col == “Column 2″, do that. Trying to use DIVs to handle this versus a table; however, the problem is that each row in the loop, it seems to place a hard return, so the next row no matter what column is below the previous one.

    COL 1 COL 2
    First:
    Last:
    Address:
    City:

    Instead of
    COL 1 COL 2
    First: Last:
    Address: City:

    I am sure it has to do with DIVs but in the case, I am not doing this right, please advise.

    
    
    			{form_fields}
    
     
    	{if "{ff_col}"  == "Column 1"}
    
    		  
    
     
    					{if "{ff_label}"}
    						{ff_label}: {if "{ff_required}" == "y"}*{/if}
    					{/if}
     
    
     
    					{if "{ff_type}" == "Text Input"}
    
    					{if:elseif "{ff_type}" == "Textarea" && "{ff_options}"}
    
    					{if:elseif "{ff_type}" == "Checkbox"}
    
    					{if:elseif "{ff_type}" == "Select" || "{ff_type}" == "Multi-select" && "{ff_options}"}
    
    								<option value="">
    
    					{if:elseif "{ff_type}" == "Radio Group" && "{ff_options}"}
    
    								<input type="radio" class="radio" name="{ff_field}" id="{ff_field}" value="" />
    								<label for="{ff_field}">
    
    					{if:elseif "{ff_type}" == "Checkbox Group" && "{ff_options}"}
    
    								<input type="checkbox" class="checkbox" name="{ff_field}[]" id="{ff_field}" value="" />
    								<label for="{ff_field}">
    
    					{/if}
     
    
      
    
    {if:elseif "{ff_col}" == "Column 2"}
    
      
    
     
    					{if "{ff_label}"}
    						{ff_label}: {if "{ff_required}" == "y"}*{/if}
    					{/if}
     
    
     
    					{if "{ff_type}" == "Text Input"}
    
    					{if:elseif "{ff_type}" == "Textarea" && "{ff_options}"}
    
    					{if:elseif "{ff_type}" == "Checkbox"}
    
    					{if:elseif "{ff_type}" == "Select" || "{ff_type}" == "Multi-select" && "{ff_options}"}
    
    								<option value="">
    
    					{if:elseif "{ff_type}" == "Radio Group" && "{ff_options}"}
    
    								<input type="radio" class="radio" name="{ff_field}" id="{ff_field}" value="" />
    								<label for="{ff_field}">
    
    					{if:elseif "{ff_type}" == "Checkbox Group" && "{ff_options}"}
    
    								<input type="checkbox" class="checkbox" name="{ff_field}[]" id="{ff_field}" value="" />
    								<label for="{ff_field}">
    
    					{/if}
     
    
      {/if}
    
    			{/form_fields}
    
  31. @Jeff-
    Do you have an example page?

  32. @Trevor-
    Here is the page that is goofy

    http://life.cc/index.php/forms/greeters

    The Email Line I want to be on the same row as the name, as goes the state with address.

    Thoughts?

  33. @Jeff-
    You need to fix your CSS:

    .center_full .col2 {
    	clear:both;
    }

    The markup looks right.

  34. @Trevor-
    Update:

    Actually use this address.

    http://life.cc/index.php/forms/double_col

    What I am going to do for the time being is have the field_label in col 1 and have all of the actual fields in Col 2. So the other page may or may not work as I am making that change. I would prefer having it as a choice. But, as this is a loop, I think it might not be an option.

    Thanks for any advice or troubleshooting you do. I think this would be a feature others would like to accomplish since many forms are more than column.

    Jeff

  35. @Jeff-
    You don’t need a separate field for that, you can do all that with CSS.

  36. @Trevor-

    Already have that in the CSS I am afraid.

    The goal behind the separate field is that the editor can decide which column the field goes into.

  37. @Jeff-
    Sorry man, I’ve provided the suggestions that I think would fix the problem. If you are trying to have the label in the left hand column and the field in the right, I did not see the CSS for doing that.

  38. @Trevor-

    Oh well. Thanks for your help anyways. I just went back to the old trusted way with using a table and that works.

    Not real sure why the div did not work.

  39. Brilliant tutorial, Trevor. Thanks for the walk through. I really have to spend some time deconstructing the form – once it’s working for me, of course. This looks to be a massive help.

    I do have a quick question – I’m getting a “Warning: Cannot modify header information”-error on submit. Also, I noticed that there’s something amiss with the fieldframe fieldtype – some error in Fieldframe now. Have I just run into this nebulous error, or have you seen this error before?

  40. @Jim-
    Does this KB article help?

    Make sure you are using the newest version of Fieldframe and the fieldtypes.

  41. Great blog! The information you provide is quiet helpful, why I was not able to find it earlier. Anyways I’ve subscribed to your feeds, keep the good work up.

  42. Thanks, but it ended up being something else entirely, a server issue with the web account not having rights to modify anything. We’re all fixed – thanks!

  43. Thanks for the tutorial, it’s going to come in very handy!

    Unfortunately, I am having some problems with the field type though.

    I’ve downloaded and installed FreeForm, FieldFrame and Freeform Data Select. I’ve created the custom weblog field group of ‘Forms’.

    My problem is that when I create a new custom field within the Forms group, I only get the Field Type options of “Text input, Textarea, Drop-down list, Date field and Relationship” – I don’t get the option of ‘Freeform Data Select’ or ‘FF Matrix’.

    Any ideas? Any help would be greatly appreciated.

    Cheers,
    Dan

  44. @Dan-
    Have you made sure to enable the fieldtypes in the FieldFrame settings?

  45. @Trevor-
    Hi Trevor,

    Thanks for your quick response.

    That sounds like the most likely cause of the problem – can you let me know how to do this?

    Cheers,
    Dan

  46. @Dan-
    Admin > Utilities > Fieldtypes Manager

  47. @Trevor-

    Cheers Trevor!

    I had to go to:
    Admin › Utilities › Extensions Manager

    and enable the extension. Then I had to edit the settings and edit the Path and URL ‘to your “fieldtypes” folder’.

    Now I am getting all the options in the Field Type drop down.

    Thanks again for your help =D

  48. Hi Trevor,

    Great tutorial and so very useful.

    I am just having a couple of problems – when I add the return=”{form_return}” the output I am getting is this:

    http://em.org.nz/index.php/thank_you

    I have changed my Custom Fields to have the default text formatting to none and I can’t see what else I need to do?

    And also the {form_notify} doesn’t seem to be working?

    If you could shed some light that would be great.

    Thanks so much

    Nat

  49. Hi Trevor,

    The output I am getting is:

    http://em.org.nz/index.php/thank_you /

    Sorry it didn’t output it properly in the above comment.

    Cheers

    Nat

  50. Hi Trevor,

    It’s not showing correctly in the posts – it is ouputing p tags around the thank_you.

    Hope this makes sense sorry for all the posts.

    Cheers

    Nat

  51. Hi Trevor,

    All sorted – I hadn’t hidden the default text formatting for the publish form and it was picking it up from there.

    Cheers

    Nat

    • 11.19.2009 at 2:01 am
    • #
    • 11.19.2009 at 6:54 am
    • #
    • 11.21.2009 at 3:44 pm
    • #

Speak Your Mind

* Denotes Required Field

  1. To post code snippets, use <pre><code>YOUR CODE HERE</code></pre>
Me, Trevor Davis. My blue steel face…

Hi, I’m Trevor Davis

I’m a 25 year old Front-End Developer living in Arlington, VA. I work full-time at Viget Labs and freelance on the side.

I specialize in CSS, HTML, jQuery, WordPress & ExpressionEngine. See more of my work, and then hire me.

Recent Work

  • 4th District IBEW Health Fund
  • Employers Council on Flexible Compensation
  • Monica Davis
  • The National Christmas Tree
  • Matrix Group International
  • The MatriX Files
  • Wireless Career
  • George Washington Wired
  • Direct Selling 411
  • Makeup Bizz
  • InstallNET
  • National Park Foundation
See More of My Work

Asides