Part 6: Creating the XForm page – Create an EPiServer site from scratch

Posted on December 19, 2009 by Frederik Vig in EPiServer

The XForm page will help our editors collect data from their users. Editors can easily customize their forms the way that they want, and decide how to store the data (in a database, by email etc).

Lets create a new page type.

using EPiServer.Core;
using EPiServer.XForms;
using PageTypeBuilder;
 
namespace Jungle.Templates.Jungle.PageTypes
{
    [PageType(
        Name = "[Jungle] XForm page",
        Filename = "/Templates/Jungle/Pages/Xform.aspx",
        SortOrder = 1020)]
    public class XFormPage : EditorialPage
    {
        [PageTypeProperty(EditCaption = "XForm", Searchable = false, Type = typeof(PropertyXForm))]
        public virtual XForm XForm
        {
            get;
            set;
        }
    }
}

Like with StandardPage and SearchPage, we derive from EditorialPage, with the Heading and MainBody properties. We only have to add the XForm property for letting the editor choose which XForm she wishes to use.

Lets create the Xform.aspx page in Visual Studio, delete the default markup and add the master page.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="XForm.aspx.cs" Inherits="Jungle.Templates.Jungle.Pages.XForm" MasterPageFile="~/Templates/Jungle/MasterPages/Site.Master" %>
using Jungle.Templates.Jungle.PageTypes;
using PageTypeBuilder.UI;
 
namespace Jungle.Templates.Jungle.Pages
{
    public partial class XForm : TemplatePage<XFormPage>
    {
 
    }
}

After you’ve done that create a new user control called XFormControl.

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="XFormControl.ascx.cs" Inherits="Jungle.Templates.Jungle.Units.XFormControl" %>
<asp:Panel runat="server" CssClass="xForm">
	<XForms:XFormControl ID="FormControl" runat="server" ValidationGroup="XForm" />
</asp:Panel>

The code-behind file has a public property for the XForm EPiServer property. This way we can easily reuse this user control in various page types. The other thing to note is how we create the form. We have the XFormControl, what we need to do is set its FormDefinition property to our form (which we need to create). The Form is a property that uses the XFormProperty property to get the form guid, which it then uses to create a new XForm instance.

using System;
using EPiServer.XForms;
using Jungle.Templates.Jungle.PageTypes;
using PageTypeBuilder.UI;
 
namespace Jungle.Templates.Jungle.Units
{
    public partial class XFormControl : UserControlBase<BasePageData>
    {
        private XForm _form;
 
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
 
            if (this.Form == null)
            {
                return;
            }
 
            FormControl.FormDefinition = this.Form;
        }
 
        public XForm Form
        {
            get
            {
                if (_form == null)
                {
                    string formGuid = CurrentPage[this.XFormProperty] as string;
                    if (!string.IsNullOrEmpty(formGuid))
                    {
                        _form = XForm.CreateInstance(new Guid(formGuid));
                    }
                }
 
                return _form;
            }
            set
            {
                _form = value;
            }
        }
 
        public string XFormProperty
        {
            get;
            set;
        }
    }
}

For more information about the XFormControl see the SDK.

Remember to add the usercontrol to XForm.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="XForm.aspx.cs" Inherits="Jungle.Templates.Jungle.Pages.XForm" MasterPageFile="~/Templates/Jungle/MasterPages/Site.Master" %>
<%@ Register TagPrefix="Jungle" TagName="MainBody" Src="~/Templates/Jungle/Units/MainBody.ascx" %>
<%@ Register TagPrefix="Jungle" TagName="XFormControl" Src="~/Templates/Jungle/Units/XFormControl.ascx" %>
 
<asp:Content ContentPlaceHolderID="MainContentRegion" runat="server">
    <Jungle:MainBody runat="server" />
 
    <Jungle:XFormControl
            runat="server" 
            XFormProperty="XForm" />
</asp:Content>

Build and create a new XForm page with a test form.

Confirmation email

So far so good, but we also want to send a confirmation email to the user when they’ve sent the form. Just a thank you for your feedback message, or something similar. I’ve written about this previously: Sending confirmation email to the user when using EPiServer XForms. Read the blog post or download the code to see how I’ve implemented it.

One thing I’ve done, that differs from the original post, is that I’ve added a property that lets the editor edit the email text. For this I added a new property to [Jungle] XForm page:

[PageTypeProperty(
    EditCaption = "Confirmation email text",
    Searchable = true,
    Type = typeof(PropertyXhtmlString),
    LongStringSettings = (
	EditorToolOption.All ^
	EditorToolOption.Font))]
public virtual string ConfirmationEmailText
{
    get;
    set;
}

Enter key

A problem we’re facing is when users are filling out our form, and use the enter key. Instead of sending the form back to the server, they’re actually triggering the quick search button instead. The reason for this behavior is that ASP.NET web forms just uses one form for everything. Unfortunately there are no good fixes for this. One that I’ve used in the past is adding some JavaScript that detects if the enter key is pressed, and then triggers the first submit buttons click event.

The jQuery code for this:

$(function() {
    $('#id_matrix input').keypress(function(e) {
        if (e.keyCode && e.keyCode == 13) {
            $('#id_matrix :submit:first').click();
            return false;
        } else {
            return true;
        }
    });
});

You can of course modify the code to look for a button with the class “default” instead. But in my experience editors tend to forget this little detail, and they mostly only have one button anyway.

I’ve placed this code in an external JavaScript file, and added some code in XFormControl.ascx to add it.

protected override void OnInit(EventArgs e)
{
    ...
 
    if (!Page.ClientScript.IsClientScriptIncludeRegistered("Xform"))
    {
	Page.ClientScript.RegisterClientScriptInclude("Xform", Page.ResolveUrl("~/Templates/Jungle/Scripts/Xform.js"));
    }
}

Our users can now use the enter key! The drawback is that the submit button must be the first button, and that this only works when users have JavaScript enabled.

Great! We now have our form in place. Next up is Part 7: Creating the Sitemap page.

Related Posts: