Pages

Wednesday, January 25, 2012

Web Forms for Marketers – Email confirmation

For one of my last projects we’re using the email address as a username. In this project people can register them self by entering a registration form, and to create this registration form I used the Web Forms for Marketers module form Sitecore. When I created the registration form I came realize that I want people to confirm their email and password. One of the standard field types that comes with the WFM is the password confirmation, but there’s no confirmation for email. So I tried to create one with the password confirmation as example.

I took the steps below to createan email confirmation field type.

Step 1

In the content editor go to the Field Types folder of WFM, copy the Password-Confirmation to the Custom folder and rename it to Email-Confirmation.

In the content of this item, add the E-mail validation in the treelist of validations don’t change the already selected validation. Now change the User Control field to the following path: “/sitecore modules/web/Web Forms for Marketers/UI/UserControl/EmailConfirmation.ascx”

The next thing is to rename the first child of the Email-confirmation item from “Password” to “Email”. In the content change the Title Property field to “EmailTitle”, and the Default Title field from “Password” to “Email”.

Step 2
Open the project in Visual Studio and go “sitecore modules\Web\Web Forms for Marketers\UI\UserControl\PasswordConfirmation.ascx”, copy this file and rename it to EmailConfirmation.ascx. I changed everything with the word password to email, but that is something you have to see for yourself.

<%@ Control Language="C#" AutoEventWireup="true" Inherits="SitecoreSolutions.Form.UI.UserControls.EmailConfirmation" %>
<%@ Register TagPrefix="wfmcustom" Namespace="Sitecore.Form.Web.UI.Controls" Assembly="Sitecore.Forms.Custom" %>

Create a code file to inherit from and fill it with the code below (which I got with reflector from the passwordconfirmation code file). In the code change the SubFieldIds.ConfirmationId and the SubFieldIds.EmailId to the id’s of the items below the Email-Confirmation field type.

using Sitecore.Form.Core.Attributes;
using SitecoreSolutions.Form.Core.Configuration;
using Sitecore.Form.Core.Controls;
using Sitecore.Form.Core.Controls.Data;
using Sitecore.Form.Core.Utility;
using Sitecore.Form.Core.Visual;
using Sitecore.Form.Web.UI.Controls;
using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using Label = System.Web.UI.WebControls.Label;

namespace SitecoreSolutions.Form.UI.UserControls
{
 public class EmailConfirmation : ValidateUserControl, IHasTitle
 {
  protected Panel emailBorder;
  protected global::Sitecore.Form.Web.UI.Controls.Label emailTitle;
  protected Panel emailPanel;
  protected TextBox email;
  protected Label emailHelp;
  protected Panel confirmationBorder;
  protected global::Sitecore.Form.Web.UI.Controls.Label confirmationTitle;
  protected Panel confirmationPanel;
  protected TextBox confirmation;
  protected Label confimationHelp;

  public override string ID
  {
   get
   {
    return this.email.ID;
   }
   set
   {
    this.email.ID = value;
    this.emailTitle.AssociatedControlID = value;
    base.ID = value + "border";
   }
  }

  [Localize]
  [VisualFieldType(typeof(TextAreaField))]
  [VisualProperty("Email Help:", 200)]
  [VisualCategory("Appearance")]
  public string EmailHelp
  {
   get
   {
    return this.emailHelp.Text;
   }
   set
   {
    this.emailHelp.Text = value;
    if (!string.IsNullOrEmpty(this.emailHelp.Text))
     this.emailHelp.Style.Remove("display");
    else
     this.emailHelp.Style["display"] = "none";
   }
  }

  [VisualProperty("Confirm Email Help:", 500)]
  [Localize]
  [VisualCategory("Appearance")]
  [VisualFieldType(typeof(TextAreaField))]
  public string ConfirmationHelp
  {
   get
   {
    return this.confimationHelp.Text;
   }
   set
   {
    this.confimationHelp.Text = value;
    if (!string.IsNullOrEmpty(this.confimationHelp.Text))
     this.confimationHelp.Style.Remove("display");
    else
     this.confimationHelp.Style["display"] = "none";
   }
  }

  [DefaultValue("scfEmailConfirmation")]
  [VisualFieldType(typeof(CssClassField))]
  [VisualProperty("Css Class:", 600)]
  public new string CssClass
  {
   get
   {
    return this.Attributes["class"];
   }
   set
   {
    this.Attributes["class"] = value;
   }
  }

  [DefaultValue("Email")]
  [VisualProperty("Email Title:", 190)]
  [Localize]
  [VisualFieldType(typeof(EditField))]
  public string EmailTitle
  {
   get
   {
    return this.emailTitle.Text;
   }
   set
   {
    this.emailTitle.Text = value;
   }
  }

  [DefaultValue("Confirm Email")]
  [Localize]
  [VisualProperty("Confirm Email Title:", 300)]
  [VisualFieldType(typeof(EditField))]
  public string ConfirmationTitle
  {
   get
   {
    return this.confirmationTitle.Text;
   }
   set
   {
    this.confirmationTitle.Text = value;
   }
  }

  [VisualProperty("Validation:", 790)]
  [VisualCategory("Validation")]
  [VisualFieldType(typeof(SelectPredefinedValidatorField))]
  [DefaultValue("")]
  public string PredefinedValidator { get; set; }

  [VisualFieldType(typeof(RegexField))]
  [DefaultValue("")]
  [VisualCategory("Validation")]
  [VisualProperty("Regular Expression:", 800)]
  public string RegexPattern { get; set; }

  [VisualCategory("Validation")]
  [VisualProperty("Maximum Length:", 2000)]
  [DefaultValue(256)]
  public int MaxLength
  {
   get
   {
    return this.email.MaxLength;
   }
   set
   {
    this.email.MaxLength = value;
    this.confirmation.MaxLength = value;
   }
  }

  [VisualProperty("Minimum Length:", 1000)]
  [DefaultValue(0)]
  [VisualCategory("Validation")]
  public int MinLength { get; set; }

  public override ControlResult Result
  {
   get
   {
    return new ControlResult(this.ControlName, (object)this.email.Text, global::Sitecore.StringExtensions.StringExtensions.FormatWith("secure:{0}", new object[1] {(object) this.email.Text}));
   }
  }

  protected override Control ValidatorContainer
  {
   get
   {
    return (Control)this.emailBorder;
   }
  }

  protected override Control InnerValidatorContainer
  {
   get
   {
    return (Control)this.emailPanel;
   }
  }

  public string Title
  {
   get
   {
    if (string.IsNullOrEmpty(this.EmailTitle) || string.IsNullOrEmpty(this.ConfirmationTitle))
     return string.Empty;
    return string.Join("-", new string[2]
        {
          this.EmailTitle,
          this.ConfirmationTitle
        });
   }
   set
   {
   }
  }

  public EmailConfirmation()
  {
   this.CssClass = "scfEmailConfirmation";
  }

  public override bool SetValidatorProperties(BaseValidator validator)
  {
   base.SetValidatorProperties(validator);
   object obj = (object)null;
   if (validator is ICloneable)
    obj = ((ICloneable)validator).Clone();
   validator.ErrorMessage = global::Sitecore.StringExtensions.StringExtensions.FormatWith(validator.ErrorMessage, (object)this.EmailTitle, (object)this.MinLength, (object)this.MaxLength, (object)this.ConfirmationTitle);
   validator.Text = global::Sitecore.StringExtensions.StringExtensions.FormatWith(validator.Text, (object)this.EmailTitle, (object)this.MinLength, (object)this.MaxLength, (object)this.ConfirmationTitle);
   validator.ToolTip = global::Sitecore.StringExtensions.StringExtensions.FormatWith(validator.ToolTip, (object)this.EmailTitle, (object)this.MinLength, (object)this.MaxLength, (object)this.ConfirmationTitle);
   BaseValidator baseValidator1 = validator;
   string str = baseValidator1.CssClass + string.Join(string.Empty, new string[2]
      {
        " confirmationControlId.",
        this.confirmation.ID
      });
   baseValidator1.CssClass = str;
   if (obj != null && obj is BaseValidator)
   {
    BaseValidator baseValidator2 = (BaseValidator)obj;
    baseValidator2.ErrorMessage = global::Sitecore.StringExtensions.StringExtensions.FormatWith(baseValidator2.ErrorMessage, (object)this.ConfirmationTitle, (object)this.MinLength, (object)this.MaxLength, (object)this.EmailTitle);
    baseValidator2.Text = global::Sitecore.StringExtensions.StringExtensions.FormatWith(baseValidator2.Text, (object)this.ConfirmationTitle, (object)this.MinLength, (object)this.MaxLength, (object)this.EmailTitle);
    baseValidator2.ToolTip = global::Sitecore.StringExtensions.StringExtensions.FormatWith(baseValidator2.ToolTip, (object)this.ConfirmationTitle, (object)this.MinLength, (object)this.MaxLength, (object)this.EmailTitle);
    baseValidator2.ID = baseValidator2.ID + "confirmation";
    baseValidator2.ControlToValidate = this.confirmation.ID;
    if (validator.Attributes["inner"] == "1")
     this.confirmationPanel.Controls.Add((Control)baseValidator2);
    else
     this.confirmationBorder.Controls.Add((Control)baseValidator2);
   }
   return true;
  }

  protected override void OnLoad(EventArgs e)
  {
   base.OnLoad(e);
   string str1 = string.Join(string.Empty, new string[4] {" fieldid.", this.FieldID, "/", SubFieldIds.ConfirmationId} );
   TextBox textBox1 = this.email;
   
   string str2 = textBox1.CssClass + string.Join(string.Empty, new string[4] {" fieldid.", this.FieldID, "/", SubFieldIds.EmailId} );
   textBox1.CssClass = str2;
   TextBox textBox2 = this.confirmation;
   string str3 = textBox2.CssClass + str1;
   textBox2.CssClass = str3;
   MarkerLabel markerLabel1 = (MarkerLabel)WebUtil.FindFirstOrDefault(this.ValidatorContainer, (Func)(c => c is MarkerLabel));
   if (markerLabel1 == null)
    return;
   MarkerLabel markerLabel2 = (MarkerLabel)markerLabel1.Clone();
   markerLabel2.ID = markerLabel1.ID + "confirmationmarker";
   this.confirmationBorder.Controls.Add((Control)markerLabel2);
  }
 }
}

Step 3

To use the new field type open the Form Designer of a form and a new field, give it a title and select the Email-Confirmation as field type. In the appearance section on the left you see the properties appear that you can use for the email confirmation. Now save the form, publish and check the form in your site.

Wednesday, January 4, 2012

Using the Sitecore Dictionary

The Sitecore Dictionary is very useful when you want controls to display content in different languages depending on the current language (Sitecore.Context.Language).

Although the use of the dictionary looks very straight forward, I initially bumped into a small problem. My problem was that no matter what dictionary item I added, it did not display the right translation. In the end we were able to find out you need to publish the site to see the translations, even when you’re an administrator and working in the development environment.

To help you get started using the dictionary without any problems, I will describe the steps you need to make.

Step 1. Open the content editor and go to the dicotionary in the item tree. Add an item (dictionary entry) to the dictionary and make sure the selected database is the master database. Fill in the key (for every language the same) and phrase (depending on you current selected language).
If you have a dynamic part in your phrase, you can use {0} to replace that part of the content.

To organize the entries you can add folders in the dictionary, for example a folder named A for all entries starting with an A etc.

Step 2. In your code go to the place where you want to display the content. The easiest way to display the content is using
Translate.Text([key])
but, you can also use the dictionary for displaying dynamic content by using arguments/parameters. In this case you have to use the
Translate.Text([key], [parameters])

Example
This example is a custom user control that display a literal. The properties for the literal are a key and parameters. With these properties you can get the translation for the current language. As you can see in the example it is even possible to display multiline content from the dictionary, you will only have to parse it to html.

using System;
using System.Web.UI;
using Sitecore.Globalization;

namespace SitecoreSolutions.layouts.UserControls
{
 public partial class LocalizedLiteral : UserControl
 {
  public string Key { get; set; }
  public object[] Parameters { get; set; }

  protected override void OnLoad(EventArgs e)
  {
   base.OnLoad(e);

   if(Key!= null)
    LiteralLocalizedValue.Text = Transform(Parameters == null ? Translate.Text(Key) : Translate.Text(Key, Parameters));
  }

  public string Transform(string data)
  {
   data = data.Replace("\r\n", "<br/>");

   return data;
  }
 }
}

Step 3. In order to view the translations/content you always have to publish the dictionary, and voila there is your content.