WFFM Field Type ReadOnly TextBox

Posted 31 July 2017 12:00 AM by Benjamin Moles, Senior .NET Developer @ ClearPeople

This article describes a Sitecore customisation with the following sections:

  1. Motivation: Describes the reasons to implement the customisation.
  2. Usage: Describes how to use the customisation.
  3. Implementation: Describes the main details of the implementation and provides the relevant source code.
  4. Technical Details: Records the Sitecore version on which the customisation was implemented along with the version of any related module.

Motivation

A WFFM form is required to display data which needs to be provided automatically by the website without letting the user update it. This information needs to be available to the SendMail save action and stored in the form’s analytics as a form field. The OOTB functionality of Sitecore’s WFFM does not support fields that are read only to the user and displayed as a label, as shown next:

WFFM

Please notice that the styles shown above belong to the web where this solution has been applied. Other site (with OOTB styling) may look different.

Usage

After deploying the “ReadOnly TextBox” customisation a new filed type is available to all WFFM forms. Its name is “ReadOnly TextBox”.

WFFM

Any value set on this field will be displayed on the form as a read-only field, it will be stored on the form’s analytics (if enabled) and will be available to any save action such as “Send Email”. The field’s value can be set in three diverse ways. The most standardised way is by using the field’s rules. Any rule can be used to determine the field’s value. Alternatively, the field supports values passed directly in the URL query string and also on a session variable. To do so the field’s attribute named “Parameter” needs to be filled with the name of a parameter to be found either on the URL query string or on the Session. If the parameter is found its value will be automatically stored on the field.

WFFM

Implementation

Implementing a new WFFM field data type requires a class to support the required logic and a Sitecore item definition that tells WFFM about the existence of the new type and how to find its associated class (implementation). In this case, the class will be called “ReadOnlyTextBox” and will derive from “Sitecore.Form.Web.UI.Controls.SingleLineText”.


public class ReadOnlyTextBox : SingleLineText

There are two key elements on the new field type. The first one is the label that will display the fields value without letting the user edit it. It will be implemented as a “System.Web.UI.WebControls.Label” and named “displayedValue”.


protected System.Web.UI.WebControls.Label displayedValue = new System.Web.UI.WebControls.Label();

The second key element is the property “Text” which needs to be overwritten in order to update our new “displayedValue”.


        [Localize, VisualProperty("Default Value:", 100), DefaultValue("")]
        public override string Text
        {
            get
            {
                return base.Text;
            }

            set
            {
                displayedValue.Text = HttpUtility.HtmlEncode(value);
                base.Text = value;
            }
        }

The attributes on the property definition are necessary to support “Rules” as a way to set the field’s value. The two additional ways to provide the field’s value are supported by the following “ParameterName” property:


        [VisualCategory("Appearance")]
        [VisualFieldType(typeof(EditField)), Localize]
        [VisualProperty("Parameter:", 100)]
        public string ParameterName { get; set; }

The “ParameterName” property will receive the value provided by the form’s designer on the field’s attribute exposed on the form’s designer UI as “Parameter”. This value, if provided, will be used to search on the URL query string or on the session variables for the value to be displayed on the field. This logic is implemented on the method “DoRender”:


protected override void DoRender(HtmlTextWriter writer)
        {
            this.textbox.Attributes["type"] = "hidden";
            if (!this.Page.IsPostBack && !string.IsNullOrWhiteSpace(this.ParameterName))
            {
                var queryStringValue = this.Page.Request.QueryString[this.ParameterName];
                if (!String.IsNullOrEmpty(queryStringValue))
                {
                    this.Text = this.Page.Request.QueryString[this.ParameterName].ToString();
                }
                else
                {
                    var sessionValue = (string)HttpContext.Current.Session[this.ParameterName];
                    if (!String.IsNullOrEmpty(sessionValue))
                    {
                        this.Text = sessionValue;
                    }
                }

            }

            base.DoRender(writer);
        }

The rest of the class’ members are just scaffolding. The hole class code is next: File: Web\WFFM\FieldTypes\Custom\ReadOnlyTextBox.cs


using System;
using System.Web;
using System.Web.UI;
using Sitecore.Form.Core.Attributes;
using Sitecore.Form.Core.Visual;
using Sitecore.Form.Web.UI.Controls;
using System.ComponentModel;
using System.Web.UI.WebControls;

namespace Website.WFFM.FieldTypes.Custom
{
    public class ReadOnlyTextBox : SingleLineText
    {

        protected System.Web.UI.WebControls.Label displayedValue = new System.Web.UI.WebControls.Label();


        [Localize, VisualProperty("Default Value:", 100), DefaultValue("")]
        public override string Text
        {
            get
            {
                return base.Text;
            }

            set
            {
                displayedValue.Text = HttpUtility.HtmlEncode(value);
                base.Text = value;
            }
        }

        [VisualCategory("Appearance")]
        [VisualFieldType(typeof(EditField)), Localize]
        [VisualProperty("Parameter:", 100)]
        public string ParameterName { get; set; }

        protected override void DoRender(HtmlTextWriter writer)
        {
            this.textbox.Attributes["type"] = "hidden";
            if (!this.Page.IsPostBack && !string.IsNullOrWhiteSpace(this.ParameterName))
            {
                var queryStringValue = this.Page.Request.QueryString[this.ParameterName];
                if (!String.IsNullOrEmpty(queryStringValue))
               {
                    this.Text = this.Page.Request.QueryString[this.ParameterName].ToString();
                }
                else
                {
                    var sessionValue = (string)HttpContext.Current.Session[this.ParameterName];
                    if (!String.IsNullOrEmpty(sessionValue))
                    {
                        this.Text = sessionValue;
                    }
                }

            }

            base.DoRender(writer);
        }

        protected override void OnInit(EventArgs e)
        {

            this.textbox.CssClass = "scfSingleLineTextBox";
            this.help.CssClass = "scfSingleLineTextUsefulInfo";
            this.generalPanel.CssClass = "scfSingleLineGeneralPanel";
            this.title.CssClass = "scfSingleLineTextLabel";
            //this.displayedValue.CssClass = "cp-readonly";

            this.textbox.TextMode = TextBoxMode.SingleLine;

            this.Controls.AddAt(0, this.generalPanel);
            this.Controls.AddAt(0, this.title);
            this.generalPanel.Controls.AddAt(0, this.displayedValue);
            this.generalPanel.Controls.AddAt(0, this.help);
            this.generalPanel.Controls.AddAt(0, this.textbox);
        }

        public override string ID
        {
            get
            {
                return base.ID;
            }
            set
            {
                this.displayedValue.ID = value + "_readonly_text";
                base.ID = value;
                this.displayedValue.AssociatedControlID = this.textbox.ID;
            }
        }

        public ReadOnlyTextBox(HtmlTextWriterTag tag) : base(tag)
              {
        }
        public ReadOnlyTextBox() : this(HtmlTextWriterTag.Div)
              {
        }
    }
}

Once the class above is implemented and deployed, Sitecore needs to know about its existence and how to find it. This is provided by adding a new Sitecore item named “ReadOnly TextBox” in the “master” database under “/sitecore/system/Modules/Web Forms for Marketers/Settings/Field Types/Custom”. This item must me of template “/sitecore/templates/Web Forms for Marketers/Field Type” ({ECF6562F-91E7-4D79-B416-0DB3C2DBF67B}). Within the new item “ReadOnly TextBox” the following fields need to be provided:

  • Assembly: it must contain the name of the DLL where the “ReadOnlyTextBox” class is implemented.
  • Class: Full qualified name of the “ReadOnlyTextBox” class.

wffm

As usual, once the item is created it needs to be published to “web” (or any other public facing database) in order to work properly.

Technical Details

The provided code has been tested for the following Sitecore versions:

  • Sitecore: 8.0 rev. 150812
  • WFFM: 8.0 rev. 150625

Share:

Add your comment

 
 

 

Archive

Tagcloud

Digital Transformation employee engagement staff satisfaction productivity Microsoft Teams Office 365 Yammer cms content management system agile GDPR Microsoft Graph collaboration Microsoft sharepoint 2016 upgrade migration SharePoint Online 2016 Tech Trends Digital Disruption Context marketing marketing SharePoint 2010 SharePoint 2013 TFS Git security kentico Analytics intranet jquery QA Quality Assurance testing digital workspace content management websites Sitecore sitecore marketplace sitecore module cloud Microsoft Cloud Storage digital strategy technical consulting sitecore modules Experience database Sitecore 7 Sitecore 8 support account management customer experience Data Storage windows azure cms integration front end front end development prototype Cloud Storage StorSimple Front-end Development Layout SharePoint 2013 colour palette UI design website design log viewer sitecore cms website Azure big data business-critical sharepoint accessibility android apple chrome clear people clearpeople debug emulator ios mobile testing opera resize adobe desktop flash ie10 internet explorer 10 metro windows 8 bcsp SharePoint Advanced System Reporter reporting framework ControlMode form control master page placeholder publishing console SharePoint 2007 SharePoint error search search results search values software testing testing scenario audit content information architecture retention schedules PowerShell QuickLaunch scripts SharePoint server 2010 business solutions metalogix replication replicator storagepoint stena technet UK Technet picture library slideshow web part RTM released to manufacturing caml caml query MOSS 2007 query infopath