Walkthrough: Creating a register page

Abstract

Learn how to create Register User action items and classes.

This walkthrough is part one of the Prefilling forms walkthrough series and describes how to create a register page:

Note

For the example in this walkthrough, you must have the Sitecore Rocks Visual Studio plug-in.

Start by creating a sample project in Visual Studio.

To set up a Visual Studio project:

  1. In Visual Studio, create an ASP.NET web project and name it ValueProviderSample

  2. Add the following references:

    • Sitecore.ExperienceForms

    • Sitecore.ExperienceForms.Mvc

    • Sitecore.Kernel

    • Sitecore.Analytics

    • Sitecore.Mvc

    • Sitecore.MVC.Analytics

    This project is used for all walkthroughs in the Prefilling forms series.

Next, create a folder for all the custom submit action implementations.

To create a register user submit action class:

  1. In the ValueProviderSample project, add a folder named SubmitActions.

  2. In the SubmitActions folder, create another folder and name it RegisterUser.

  3. Create a class named RegisterUserData and add it to the RegisterUser folder. This is the data structure class used for our RegisterUser Submit Action implementation.

     public class RegisterUserData
    	{
    	        public Guid EmailFieldId { get; set; }
    	
    	        public Guid PasswordFieldId { get; set; }
    	
    	        public Guid FullNameFieldId { get; set; }
    	
    	        public string ProfileId { get; set; }
    }
  4. Go to the root of the project and create a folder named Helper.

  5. Create a static FieldHelper class and add it to the Helper folder that you just created. This helper class is used to get values from form fields.

    
    public static class FieldHelper
    
        {
    
            public static
    IViewModel GetFieldById(Guid id, IList<IViewModel> fields)
    
            {
    
                return
    fields.FirstOrDefault(f => Guid.Parse(f.ItemId) == id);
    
            }
    
            public static string
    GetValue(object field)
    
            {
    
                return
    field?.GetType().GetProperty("Value")?.GetValue(field, null)?.ToString()
    ?? string.Empty;
    
            }
    
  6. Create the RegisterUser class and add it to the RegisterUser folder. Inherit this class from the SubmitActionBase classand override the abstract Execute method.

    	public class RegisterUser : SubmitActionBase<RegisterUserData>
    	    {
    	        public RegisterUser(ISubmitActionData submitActionData) : base(submitActionData)
    	        {
    	        }
    	
    	        protected override bool Execute(RegisterUserData data, FormSubmitContext formSubmitContext)
    	        {
    	            Assert.ArgumentNotNull(data, nameof(data));
    	            Assert.ArgumentNotNull(formSubmitContext, nameof(formSubmitContext));
    	
    	            var fields = GetFormFields(data, formSubmitContext);
    	
    	            Assert.IsNotNull(fields, nameof(fields));
    	
    	            if (EmailOrPasswordFieldsIsNull(fields))
    	            {
    	                return AbortForm(formSubmitContext);
    	            }
    	
    	            var values = fields.GetFieldValues();
    	
    	            if (EmailOrPasswordsIsNull(values))
    	            {
    	                return AbortForm(formSubmitContext);
    	            }
    	
    	            var result = Register(values.Email, values.Password, values.FullName, data.ProfileId);
    	
    	            if (!result)
    	            {
    	                return AbortForm(formSubmitContext);
    	            }
    	
    	            return true;
    	        }
    	
    	        protected virtual bool Register(string email, string password, string name, string profileId)
    	        {
    	            Assert.ArgumentNotNullOrEmpty(email, nameof(email));
    	            Assert.ArgumentNotNullOrEmpty(password, nameof(password));
    	
    	            try
    	            {
    	                var user = User.Create(Context.Domain.GetFullName(email), password);
    	                user.Profile.Email = email;
    	
    	                if (!string.IsNullOrEmpty(profileId))
    	                {
    	                    user.Profile.ProfileItemId = profileId;
    	                }
    	
    	                user.Profile.FullName = name;
    	                user.Profile.Save();
    	            }
    	            catch (Exception ex)
    	            {
    	                Log.SingleError("Register user failed", ex);
    	                return false;
    	            }
    	
    	            return true;
    	        }
    	
    	        private RegisterUserFormFields GetFormFields(RegisterUserData data, FormSubmitContext formSubmitContext)
    	        {
    	            Assert.ArgumentNotNull(data, nameof(data));
    	            Assert.ArgumentNotNull(formSubmitContext, nameof(formSubmitContext));
    	
    	            return new RegisterUserFormFields
    	            {
    	                Email = FieldHelper.GetFieldById(data.EmailFieldId, formSubmitContext.Fields),
    	                Password = FieldHelper.GetFieldById(data.PasswordFieldId, formSubmitContext.Fields),
    	                FullName = FieldHelper.GetFieldById(data.FullNameFieldId, formSubmitContext.Fields),
    	            };
    	        }
    	
    	        private bool EmailOrPasswordFieldsIsNull(RegisterUserFormFields field)
    	        {
    	            Assert.ArgumentNotNull(field, nameof(field));
    	            return field.Email == null || field.Password == null;
    	        }
    	
    	        private bool EmailOrPasswordsIsNull(RegisterUserFieldValues values)
    	        {
    	            Assert.ArgumentNotNull(values, nameof(values));
    	            return string.IsNullOrEmpty(values.Email) || string.IsNullOrEmpty(values.Password);
    	        }
    	
    	        private bool AbortForm(FormSubmitContext formSubmitContext)
    	        {
    	            formSubmitContext.Abort();
    	            return false;
    	        }
    	        
    	        internal class RegisterUserFormFields
    	        {
    	            public IViewModel Email { get; set; }
    	            public IViewModel Password { get; set; }
    	            public IViewModel FullName { get; set; }
    	
    	            public RegisterUserFieldValues GetFieldValues()
    	            {
    	                return new RegisterUserFieldValues
    	                {
    	                    Email = FieldHelper.GetValue(Email),
    	                    Password = FieldHelper.GetValue(Password),
    	                    FullName = FieldHelper.GetValue(FullName)
    	                };
    	            }
    	        }
    	
    	        internal class RegisterUserFieldValues
    	        {
    	            public string Email { get; set; }
    	            public string Password { get; set; }
    	            public string FullName { get; set; }
    	        }
    	    }
    

Before you can create the Register User submit action item, you must create the SPEAK control editor for mapping the form fields to the RegisterUserData.

Note

For the example in this walkthrough, you must have the Sitecore Rocks Visual Studio plug-in.

To create the Register User Action Editor item:

  1. In your Visual Studio project, create a folder and name it Scripts.

  2. Create a JavaScript file and name it RegisterUser.js. This file is used for the Register User Action Editor item.

    FORMS-register-user-scripts.png
  3. Copy the following script to the file:

    (function (speak) {
    
        var parentApp = window.parent.Sitecore.Speak.app.findApplication('EditActionSubAppRenderer'),
    
            designBoardApp = window.parent.Sitecore.Speak.app.findComponent('FormDesignBoard');
    
        var getFields = function () {
    
            var fields = designBoardApp.getFieldsData();
    
            return _.reduce(fields,
    
                function (memo, item) {
    
                    if (item && item.model && item.model.hasOwnProperty("value")) {
    
                        memo.push({
    
                            itemId: item.itemId,
    
                            name: item.model.name
    
                        });
    
                    }
    
                    return memo;
    
                },
    
                [
    
                    {
    
                        itemId: '',
    
                        name: ''
    
                    }
    
                ],
    
                this);
    
        };
    
        speak.pageCode(["underscore"],
    
            function (_) {
    
                return {
    
                    initialized: function () {
    
                        this.on({
    
                            "loaded": this.loadDone
    
                        },
    
                            this);
    
                        this.Fields = getFields();
    
                        this.MapRegisterUserForm.children.forEach(function (control) {
    
                            if (control.deps && control.deps.indexOf("bclSelection") !== -1) {
    
                                control.IsSelectionRequired = false;
    
                            }
    
                        });
    
                        this.ItemTreeView.on("change:SelectedItem", this.changedSelectedItemId, this);
    
                        if (parentApp) {
    
                            parentApp.loadDone(this, this.HeaderTitle.Text, this.HeaderSubtitle.Text);
    
                            parentApp.setSelectability(this, true);
    
                        }
    
                    },
    
                    changedSelectedItemId: function () {
    
                        parentApp.setSelectability(this, true, this.ItemTreeView.SelectedItemId);
    
                    },
    
                    setDynamicData: function (propKey) {
    
                        var componentName = this.MapRegisterUserForm.bindingConfigObject[propKey].split(".")[0];
    
                        var component = this.MapRegisterUserForm[componentName];
    
                        var items = this.Fields.slice(0);
    
                        if (this.Parameters[propKey] &&
    
                            !_.findWhere(items, { itemId: this.Parameters[propKey] })) {
    
                            var currentField = {
    
                                itemId: this.Parameters[propKey],
    
                                name: this.Parameters[propKey] +
    
                                    " - " +
    
                                    (this.ValueNotInListText.Text || "value not in the selection list")
    
                            };
    
                            items.splice(1, 0, currentField);
    
                            component.DynamicData = items;
    
                            $(component.el).find('option').eq(1).css("font-style", "italic");
    
                        } else {
    
                            component.DynamicData = items;
    
                        }
    
                    },
    
                    loadDone: function (parameters) {
    
                        this.Parameters = parameters || {};
    
                        _.keys(this.MapRegisterUserForm.bindingConfigObject).forEach(this.setDynamicData.bind(this));
    
                        this.MapRegisterUserForm.BindingTarget = this.Parameters;
    
                        this.ItemTreeView.SelectedItemId = this.Parameters.profileId;
    
                    },
    
                    getData: function () {
    
                        var formData = this.MapRegisterUserForm.getFormData(),
    
                            keys = _.keys(formData);
    
                        keys.forEach(function (propKey) {
    
                            if (formData[propKey] == null || formData[propKey].length === 0) {
    
                                if (this.Parameters.hasOwnProperty(propKey)) {
    
                                    delete this.Parameters[propKey];
    
                                }
    
                            } else {
    
                                this.Parameters[propKey] = formData[propKey];
    
                            }
    
                        }.bind(this));
    
                        this.Parameters.profileId = this.ItemTreeView.SelectedItemId;
    
                        return this.Parameters;
    
                    }
    
                };
    
            });
    
    })(Sitecore.Speak);
  4. In Visual Studio, open Sitecore Explorer and establish a connection to your Sitecore instance. Using Sitecore Rocks Folder Sync, deploy the RegisterUser.js  file to your website in the following folder: sitecore/shell/client/Applications/FormsBuilder/Layouts/Actions.

    Path to Actions folder.
  5. To create a Register User Action Editor Sitecore item, in your Sitecore Explorer, expand the core database and go to sitecore/shell/client/Applications/FormsBuilder/Layouts/Actions.

  6. Right-click Actions, click Add, and click New item.

  7. In the Add New Item dialog box, search for and click Speak-BasePage , enter the name RegisterUser, and click OK.

    image2.png
  8. Right-click the RegisterUser item you just created and click Tasks, and click Design Layout.

  9. On the Design Layout tab of the item that you just added, update the Layout field to Speak-FlexLayout.

  10. In the upper-left corner, click Add Rendering and insert a PageCode rendering.

    image5.png
  11. Open the properties window of the PageCode rendering. Update the PageCodeScriptFileName value to the file location of the RegisterUser.js file. For example:

    /sitecore/shell/client/Applications/FormsBuilder/Layouts/Actions/RegisterUser.js .

  12. Update the SpeakCoreVersion value to SPEAK 2-x.

    FORMS-register-user-speak.png
  13. Then, proceed to these renderings at the Design Layout window.

    FORMS-register-user-renderings.png

Add the text rendering parameters

  1. Go to the RegisterUser Action Editor item you just created, and add a PageSettings item.

  2. Go to the PageSettings item, and search for and click the Text Parameters rendering, and click Add to add three items: HeaderTitleHeaderSubtitle, and ValueNotInListText

    Note

    You must use the sitecore/client/Business Component Library/version2 

  3. For the three items, click and edit the following fields:

    • IsVisible – Deselect

    • Edit the text:

      HeaderTitle: Map form fields to user registration data

      HeaderSubtitle: Map the fields in the form to the user profile details

      ValueNotInListText: Value not in the selection list.      

  4. Go to the PageSettings item, add a folder, and name it MapRegisterUserForm.

  5. Search for and click the FormDropList Parameters, click Add to add:

    • Email

    • Password

    • FullName

  6. Update the field values of these items according to the following table:

    FormDropList Parameter

    ValueFieldName

    DisplayFieldName

    FormLabel

    BindingConfiguration

    Email

    itemId

    name

    Email

    emailFieldId/SelectedValue

    Password

    itemId

    name

    Password

    passwordFieldId/SelectedValue

    FullName

    itemId

    name

    Full Name

    fullNameFieldId/SelectedValue

  7. In Sitecore Explorer, go to the PageSettings item and add an ItemTreeView Parameters item and name it ItemTreeView.

  8. Update the StaticData field values of the ItemTreeView  item by clicking Browse.

  9. Go to  /sitecore/system/Setttings/Security/Profiles, click the Profiles folder,and click OK.

    image10.png
  10. Set the Database field value to core.

  11. Finally, add a Page-Stylesheet-File item and name it Stylesheet. Update the Stylesheet field value to /sitecore/shell/client/Applications/FormsBuilder/Layouts/Actions/Actions.css:

    image11.png

Your rendering list now looks like this:

image12.png

To create the register user submit action item:

  1. In the Content Editor, go to sitecore/System/Settings/Forms/Submit Actions.

  2. Right-click Submit Actions, click Insert, and click Insert from template.

  3. Click the /System/Forms/Submit Action template, in the Item Name field, enter the name Register User and click Insert.

    image13.png
  4. Go to the item you just created and in the Settings section, in the Model Type field, set the value to your RegisterUser class type name: ValueProviderSample.SubmitActions.RegisterUser.RegisterUser

  5. In the Error Message field, enter the error message: Register user failed!

  6. In the Editor field, click the editor you just created: RegisterUser.

    FORMS-register-user-field.png
  7. Save the item.

To create a form:

  1. On the Forms dashboard, click Create.

  2. Create a form with the following fields:

    Type

    Label

    Field Name

    CSS class

    Single-line text

    Full Name           

    Full Name

    form-control

    Email

    Email

    Email

    form-control

    Password Confirmation           

    Password

    Password Confirmation           

    form-control

    Submit Button

    Register

    Submit Button

    btn btn-default           

  3. Optionally, add some sections to group the form fields:

    Field Name

    Form field (s)/Section(s)

    CSS class

    UserDataSection

    EmailSection, PasswordSection           

    form-group col-md-6

    EmailSection

    Full Name, Email

    form-group

    PasswordSection

    (Password Confirmation)

    form-group

    SubmitSection

    Submit Button

    form-group col-md-12           

    The form will look like this:

    image15.png
  4. To add a Submit button on your form, in the Form elements pane, in the Structure section, drag the Submit button element to the form.

  5. Click Submit actions and click Register User.

    image16.png
  6. In the Map form fields to user registration data dialog box, select the corresponding form fields.

  7. Expand the tree view, click the User node and click OK.

    image17.png
  8. Save the form and name it: Register Form.

Before you can add  the form to a web page, you must create an MVC Layout.

To create an MVC Layout:

  1. In your website Views folder, create a folder and name it ValueProvider.

    FORMS-register-user-view.png
  2. In the Content Editor, go to Layout/Layouts, and insert a layout folder and name it  Value Provider.

    FORMS-register-user-valueprovider.png
  3. Right-click the Value Provider folder and click Insert and MVC Layout.

  4. Name the layout MVC Layout and place it in the Value Provider folder that you created earlier.

  5. Go to your Visual Studio project and create a folder named Views.

  6. Create an empty view without model named MVC Layout.cshtml. The name of the View must be the same as the name of the MVC layout that you created in the Content Editor:

    @using Sitecore.Mvc
    
    @{
    
    Layout = "~/Views/Mvc OuterLayout.cshtml";
    
    }
    
    <nav class="navbar navbar-inverse navbar-fixed-top">
    
    <div class="container">
    
    <div class="navbar-header">
    
    <a class="navbar-brand" href="#">@Html.Sitecore().Field("title")</a>
    
    </div>
    
    @RenderPage("~/Views/_LoginPartial.cshtml")
    
    </div>
    
    </nav>
    
    <div class="container">
    
    <div class="row">
    
    @Html.Sitecore().Placeholder("main")
    
    </div>
    
    </div>
    
    
    
  7. Create another empty view named _LoginPartial.cshtml and copy the following code.

    	@using Sitecore.Mvc
    	@if (Request.IsAuthenticated)
    	{
    	    var fullname = "Hello " + Sitecore.Context.User.Profile.FullName + "!";
    	    <ul class="nav navbar-nav navbar-right">
    	        <li>
    	            <a href="UserProfile">@fullname</a>
    	        </li>
    	        <li style="padding-top: 8px;">
    	            @Html.Sitecore().Placeholder("logout")
    	        </li>
    	    </ul>
    	}a
    	else
    	{
    	
    	<ul class="nav navbar-nav navbar-right">
    	    <li>
    	        <a href="Login">Login</a>
    	    </li>
    	    <li>
    	        <a href="Register">Register</a>
    	    </li>
    	</ul>
    	
    	}
    
    
  8. In the same folder, create a file named Mvc OuterLayout.cshtml and copy the following code to the file:

    @using Sitecore.Mvc
    
    @using Sitecore.ExperienceForms.Mvc.Html
    
    @using Sitecore.Mvc.Analytics.Extensions
    
    @{
    
    Layout = null;
    
    }
    
    <!DOCTYPE html>
    
    <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
    
    <head>
    
    <title>@Html.Sitecore().Field("title", new { DisableWebEdit = true })</title>
    
    @Html.Sitecore().VisitorIdentification()
    
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    
    <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/latest/css/font-awesome.min.css">
    
    @Html.RenderFormStyles()
    
    @Html.RenderFormScripts()
    
    </head>
    
    <body style="padding-top: 70px;">
    
    @RenderBody()
    
    </body>
    
    </html>

    Your View folder will look like this

    FORMS-register-user-views-folder.png
  9. Deploy all Views to your Views/ValueProvider folder in your website using Sitecore Rock Folder Sync.

To add the register form to the web page:

  1. Go to /sitecore/Content, right-click Home, click Insert, click Sample item.

  2. Enter Register and click OK.

  3. On the Presentation tab, click Details. In the Layout Details dialog box, click the default layout to change it.

  4. In the Device Editor dialog box, from the drop-down list, click Layouts/MVC Layout.

  5. On the Controls tab, remove all the renderings, and click Add.

  6. Go to Renderings/System/Forms and click Mvc Form. In the Select a Rendering dialog box, in the Add to Placeholder field, enter main, and then click Select.

  7. On the Controls tab, click the MVC form control and click Edit. In the Data Source field, click Browse and select the form you want to add to the page. For this example, select Register Form.

  8. Publish the form, layouts, and items along with their children in previous steps.

    Note

    Make sure the workflow state of the items is in the Approved state.

  9. Load the register page in a browser and register a user.

    image21.png

Go the next walkthrough to learn how to create a login and logout page.