Walkthrough: Creating a Custom Form Element with Multiple Fields
In this blog, we will be making a custom address form element as an example. It will contain fields for address, city/town, province/state, postal code, and country.
Create a Template for the Fields
- Right click on
/sitecore/templates/System/Forms/Fields
and insert a new template named Address Complete. -
After it’s created, switch over to the
Content
tab. There should be a Data section with a Base template field. AddTemplates/System/Forms/Fields/Field
. -
Go back to the
Builder
tab and add a Section namedAddress
. Add the following fields with the Type Single-Line Text.- Address Label
- Address Label Css Class
- Address Css Class
- Address Div Css Class
- Address Placeholder Text
-
Add a Section named
City
and the following fields. TheField Name
is the important field, but we will get to that later.City Label, City Label Css Class, City Css Class, City Div Css Class, City Placeholder Text, City Field Name
-
Add a section named
Province
Province Label, Province Label Css Class, Province Css Class, Province Div Css Class, Province Field Name
-
Add a section named
Postal Code
Postal Code Label, Postal Code Label Css Class, Postal Code Css Class, Postal Code Div Css Class, Postal Code Placeholder Text, Postal Code Field Name
-
And finally, a section named
Country Label, Country Label Css Class, Country Css Class, Country Div Css Class, Country Field Name
-
Now to go the Builder Options ribbon at the top and add
Standard values
. Without standard values, you will not be able to add the element inside form builder. You can fill out the Standard values however you want. I did something simple like this:
Creating a New Class
Now it’s time to go into the code. In Visual Studio, create a new class named AddressCompleteViewModel.cs
. Here’s what mine looks like with just the Address fields included to save space. Please read the comments for more details.
using Sitecore;
using Sitecore.Data.Items;
using Sitecore.ExperienceForms.Mvc.Models.Fields;
using System;
namespace MyProject.Feature.Sitecore.Forms.Fields
{
[Serializable]
public class AddressCompleteViewModel : StringInputViewModel
{
public string ErrorMessage { get; set; }
//Address fields. Copy the name of the fields in the Address Complete template, but remove the spaces; it increases readability
public string AddressLabelCssClass { get; set; }
public string AddressCssClass { get; set; }
public string AddressDivCssClass { get; set; }
public string AddressPlaceholderText { get; set; }
// add the rest of the fields here
// Create an override for InitItemProperties
protected override void InitItemProperties(Item item)
{
// on form load
base.InitItemProperties(item);
// Initialize the address fields. They will be the Standard values at first
AddressLabel = StringUtil.GetString(item.Fields["Address Label"]);
AddressLabelCssClass = StringUtil.GetString(item.Fields["Address Label Css Class"]);
AddressCssClass = StringUtil.GetString(item.Fields["Address Css Class"]);
AddressDivCssClass = StringUtil.GetString(item.Fields["Address Div Css Class"]);
AddressPlaceholderText = StringUtil.GetString(item.Fields["Address Placeholder Text"]);
// add the rest of the fields here
}
// override UpdateItemFields
protected override void UpdateItemFields(Item item)
{
// upon save
base.UpdateItemFields(item);
// Save updated fields
item.Fields["Address Label"]?.SetValue(AddressLabel , true);
item.Fields["Address Label Css Class"]?.SetValue(AddressLabelCssClass, true);
item.Fields["Address Css Class"]?.SetValue(AddressCssClass, true);
item.Fields["Address Div Css Class"]?.SetValue(AddressDivCssClass, true);
item.Fields["Address Placeholder Text"]?.SetValue(AddressPlaceholderText, true);
// add the rest of the fields here
}
}
}
Create a View File
Next, let’s create a view file to go with our new class. I’ve named it AddressComplete.cshtml
. The default location for Sitecore Forms views are stored inside website/Views/Formbuilder/FieldTemplates
. I stored mine inside website/Views/Formbuilder/Custom
.
@using Sitecore.ExperienceForms.Mvc.Html
@model MyProject.Feature.Sitecore.Forms.Fields.AddressCompleteViewModel
<div class="@Model.CssClass">
<div class="@Model.AddressDivCssClass">
<label for="@Html.IdFor(m => Model.Value)" class="@Model.AddressLabelCssClass">@Model.AddressLabel</label>
<input id="@Html.IdFor(m => Model.Value)" name="@Html.NameFor(m => Model.Value)" class="@Model.AddressCssClass" type="text" value="@Model.Value" placeholder="@Model.PlaceholderText" data-sc-field-name="@Model.Name" />
</div>
<div class="@Model.CityDivCssClass">
<label class="@Model.CityLabelCssClass">@Model.CityLabel</label>
<input id="@Html.IdFor(m => Model.CityValue)" name="@Html.NameFor(m => Model.CityValue)" value="@Model.CityValue" type="text" class="@Model.CityCssClass" placeholder="@Model.CityPlaceholderText" data-sc-field-name="@Model.CityFieldName" />
</div>
<div class="@Model.ProvinceDivCssClass">
<label class="@Model.ProvinceLabelCssClass">@Model.ProvinceLabel</label>
<input id="@Html.IdFor(m => Model.ProvinceValue)" name="@Html.NameFor(m => Model.ProvinceValue)" value="@Model.ProvinceValue" type="text" class="@Model.ProvinceCssClass" data-sc-tracking="@Model.IsTrackingEnabled" data-sc-field-name="@Model.ProvinceFieldName" />
</div>
<div class="@Model.PostalCodeDivCssClass">
<label class="@Model.PostalCodeLabelCssClass">@Model.PostalCodeLabel</label>
<input id="@Html.IdFor(m => Model.PostalCodeValue)" name="@Html.NameFor(m => Model.PostalCodeValue)" value="@Model.PostalCodeValue" type="text" class="@Model.PostalCodeCssClass" placeholder="@Model.PostalCodePlaceholderText" data-sc-tracking="@Model.IsTrackingEnabled" data-sc-field-name="@Model.PostalCodeFieldName" />
</div>
<div class="@Model.CountryDivCssClass">
<label class="@Model.CountryLabelCssClass">@Model.CountryLabel</label>
<input id="@Html.IdFor(m => Model.CountryValue)" name="@Html.NameFor(m => Model.CountryValue)" value="@Model.CountryValue" type="text" class="@Model.CountryCssClass" data-sc-tracking="@Model.IsTrackingEnabled" data-sc-field-name="@Model.CountryFieldName" />
</div>
</div>
Create the Form Elements Pane for Forms Builder
Our next goal is to create a drag and droppable element inside the Sitecore Forms Builder, as well as have editable fields. Here’s a few pictures of our end goal.
- Switch to the Core database and open up the Content Editor.
-
Navigate to
/sitecore/client/Applications/FormsBuilder/Components/Layouts/PropertyGridForm/PageSettings/Settings
. If you’re looking for it manually, FormsBuilder is actually labeled Forms. -
Right click on the folder, and hit Insert from Template, using
/sitecore/client/Business Component Library/version 2/Layouts/Renderings/Forms/Form/Form Parameters
. Name itAddressComplete
, and make sureIsVisible
is checked. -
Right click on the new AddressComplete item and Insert from template again, this time using
/sitecore/client/Applications/FormsBuilder/Common/Templates/FormSection
. Add fiveFormSection
items, naming them:- Address
- City
- Province
- PostalCode
- Country
There are two fields for our new items, ConfigurationItem, and ControlDefinitions. They must all be unique. Any duplicates will have the FormsBuilder spinning and a vague error message appearing in the console.
Create New Expanders for ConfigurationItem
- Go to
/sitecore/client/Applications/FormsBuilder/Components/Layouts/PropertyGridForm/PageSettings/Common/Sections
. Right-click and add a new folder from the template/sitecore/templates/Common/Folder
named AddressComplete. - Inside the new AddressComplete folder, add five new items using this template:
/sitecore/client/Business Component Library/version 2/Layouts/Renderings/Containers/Expander/Expander Parameter
. As you’ve probably already guessed, name them:- AddressExpander
- CityExpander
- CountryExpander
- PostalCodeExpander
- ProvinceExpander
- Now lets go back to ~/Property Editor Settings/AddressComplete and edit the ConfigurationItem field for each FormSection item.
- e.g. Address: change the value in the dropdown to
sitecore/client/Applications/FormsBuilder/Components/Layouts/PropertyGridForm/PageSettings/Common/Sections/AddressComplete/AddressExpander
. - Repeat with the four remaining items.
- e.g. Address: change the value in the dropdown to
Create ControlDefinitions for each FormSection
- Right click on Address and Insert from template using:
/sitecore/client/Business Component Library/version 2/Layouts/Renderings/Forms/Form/Templates/FormTextBox Parameters
. - Create items with the same names as the template.
- Address Css Class
- Address Div Css Class
- Address Placeholder Class
- etc
-
Here are the Appearance settings for the items.
-
Scroll down to the
Form
section and fill it out like so. In theBindingConfiguration
, use the same name as the template name, but in camelCase, eg. Address Div Css Class → addressDivCssClass. -
Do this for Address, City, Province, PostalCode, and Country. You should end up with a tree looking like this:
-
Edit the ControlDefinitions for each FormSection. Let’s do Address as it will be a little different.
-
We will actually be using the default Sitecore FieldName for Address, which ensures we can have multiple Address Complete elements on the form (as long as the FieldName is unique). You can find FieldName under
sitecore/client/formsbuilder/components/layouts/PropertyGridForm/PageSettings/Common/Details/FieldName
. -
I used Sitecore’s default label, but you can use the custom Address Label field we created.
-
The rest of the items can be found under the FormSection we just created. Ignore the extra items I’ve added for testing.
-
Now do this for Country, City, Province, and PostalCode as well. For example, City should end up looking like this:
-
Creating the Field Type Item
- Go back to the master database, and go to
/sitecore/system/Settings/Forms/Field Types/Basic
. - Right click, and Insert from template using
/sitecore/templates/System/Forms/Field Type
.- View Path - This is the path to our view. We used Custom/AddressComplete.
- Model Type - Our viewmodel. Ours will be
MyProject.Feature.Sitecore.Forms.Fields.AddressCompleteViewModel, MyProject.Feature.Sitecore
. - Property Editor - This is what we just created in the core database. Select
Property Editor Settings/AddressComplete
. - Field Template - The template we created at the beginning of this walkthrough. Set it to
Fields/Address Complete
. - Icon - I chose
OfficeWhite/32x32/map_location2.png
because it looks like a map. This will be the icon for the Address Complete element in the Forms Builder. - BackgroundColor - I chose Carrot. You can choose anything. This is the background color for the Address Complete element in the Forms Builder
And that is it! Open up the Forms Builder and you should see the Address Complete element under Form elements.
Drag and drop it into your new form, and start editing. Here’s what mine looks like:
Here’s a few of my CSS classes. I used Bootstrap
- Address Div Css Class: col-sm-12 mb-4
- City Div Css Class: col-sm-6 mb-4
- Province Div Css Class: col-sm-6 mb-4
- Country Div Css Class: col-sm-6 mb-4
Final Result
And here’s what it looks like after I’ve published it:
Thank you for reading my walkthrough. I hope it helped!