allBlogsList

Sitecore 9 - Json to Forms

Sitecore 9 Forms is a powerful upgrade from WFFM. It provides a simple interface that allows the user to easily create forms on demand, and collect information from their visitors. For longer forms, the creation process can be a bit tedious and repetitive. This prompted me to leverage Sitecore PowerShell to create a script that will parse a JSON file and generate a form. Now the repetitive stuff can be managed via copy/paste. All of the scripts and an installation package can be found over at GitHub: Sitecore - Json To Forms. I will dive into some of the details below.

As with everything in Sitecore, each piece of a form is just a Sitecore item. After creating my form, I took a look at the resulting content tree and determined that PowerShell could certainly make my life easier. First step was to identify the templates utilized for each field type available in the default fields:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

$fieldTemplates = @{

Form                 = ``'{6ABEE1F2-4AB4-47F0-AD8B-BDB36F37F64C}'``;

Button               = ``'{94A46D66-B1B8-405D-AAE4-7B5A9CD61C5E}'``;

Checkbox             = ``'{2F07293C-077F-456C-B715-FDB791ACB367}'``;

Date                 = ``'{5AC7621E-9F18-4569-BCEC-F5BF8BA1F4D7}'``;

DropdownList         = ``'{9121D435-48B8-4649-9D13-03D680474FAD}'``;

Email                = ``'{886ADEC1-ABF8-40E1-9926-D9189C4E8E1B}'``;

Field                = ``'{84ED565A-BEC9-46D4-9603-6E0516580832}'``;

List                 = ``'{5B672865-55D2-413E-B699-FDFC7E732CCF}'``;

ListBox              = ``'{81FE389A-FDC7-4ECA-A5A9-4BE3ACA0C69A}'``;

MultipleLineText     = ``'{D8386D04-C1E3-4CD3-9227-9E9F86EF3C88}'``;

Number               = ``'{E8D5A5A3-6430-4701-BAAD-1DB1947616CC}'``;

Password             = ``'{05D71800-56BE-4A53-AFAB-3819DA817A4A}'``;

PasswordConfirmation = ``'{52FEC879-7D8D-46D3-BBB2-131293957709}'``;

Text                 = ``'{FC18F915-EAC6-460A-8777-6E1376A9EA09}'``;

Page                 = ``'{CFEE7B51-8505-45CE-B843-9358F827DF87}'``;

Section              = ``'{8CDDB194-F456-4A75-89B7-346F8F39F95C}'``;

Input                = ``'{0908030B-4564-42EA-A6FA-C7A5A2D921A8}'``;

}

After identifying the necessary field templates, I needed to come up with a JSON structure that provides a sensible method for me to define items in a good hierarchy. All forms start with their root level declaration, leveraging the Form template type. After that, it's just a matter of listing all of the elements in that form. Given the nature of Sections, those elements can have elements of their own. Each field type has its own set of fields that need values. For those, we just need to normalize the field names to be JSON friendly, and we're off to the races. Given all of this, it's very simple to come up with a basic JSON structure:

{
  "name": "Meeting Proposal Test",
  "fieldType": "Form",
  "elements": [
    {
      "name": "Page",
      "fieldType": "Page",
      "elements": [
        {
          "name": "",
          "fieldType": "Section",
          // ... more properties
          "elements": [
            {
              "name": "",
              "fieldType": "Date",
              "title": "",
              // ... more properties
            }
          ]
        },
      ]
    }
  ]
}

For the properties not listed in this blog, I simply converted the title case field names to camel case JSON property names (e.g. Css Class ==> cssClass).

The last thing to do is to put together a script that will take a JSON string, and generate some Sitecore items. 

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

# Recursive method to read elements and import items

function Invoke-ProcessElements(

[array]$elements,

[``string``]$rootPath

) {

$sortOrder = 0

foreach ($element ``in $elements) {

$templateTypeId = $fieldTemplates.$($element.fieldTemplate)

$newItem = New-Item -Path ``"master:$($rootPath)\$($element.Name)" -ItemType $templateTypeId

$itemProperties = @{ }

$isFormField = $``false

switch ($element.fieldTemplate) {

"Form" {

Set-FormProperties $itemProperties $element

break``;

}

"Button" {

Set-ButtonProperties $itemProperties $element

CreateSubmitActions $newItem $element

break``;

}

"Checkbox" {

Set-CheckboxProperties $itemProperties $element

$isFormField = $``true

break``;

}

"DrowdownList" {

Set-DropDownListProperties $itemProperties $element

CreateListOptions $newItem $element

$isFormField = $``true

break``;

}

"Email" {

# Email is just an input with an Email Validator on it

Set-EmailProperties $itemProperties $element

$isFormField = $``true

break``;

}

"Field" {

break``;

}

"List" {

Set-SelectionProperties $itemProperties $element

CreateListOptions $newItem $element      

$isFormField = $``true

break``;

}

"ListBox" {

break``;

}

"MultipleLineText" {

Set-InputProperties $itemProperties $element

Set-MultipleLineProperties $itemProperties $element

$isFormField = $``true

break``;

}

"Number" {

Set-NumberProperties $itemProperties $element

$isFormField = $``true

break``;

}

"Password" {

Set-PasswordProperties $itemProperties $element

$isFormField = $``true

break``;

}

"PasswordConfirmation" {

Set-PasswordProperties $itemProperties $element

Set-ConfirmPasswordProperties $itemProperties $element

$isFormField = $``true

break``;

}

"Text" {

Set-TextProperties $itemProperties $element

break``;

}

"Date" {

Set-DateProperties $itemProperties $element

$isFormField = $``true

break``;

}

"Input" {

Set-InputProperties $itemProperties $element

$isFormField = $``true

break``;

}

}

Add-StringProperty $itemProperties ``"Css Class" "cssClass" $element

Add-FieldTypeProperty $itemProperties $element

$itemProperties.Add(``"__Sortorder"``, $sortOrder)

$sortOrder += 100

if ($isFormField) {

Set-FormFieldProperties $itemProperties $element

}

Update-NewItem $newItem $itemProperties

if ($element.elements.count -gt 0) {

Invoke-ProcessElements $element.elements $newItem.Paths.FullPath

}

}

}

$formDataFilePath = Read-Host ``"Enter path to form data configuration file: "

$formDataItem = Get-Item -Path master:$($formDataFilePath)

$formJson = $formDataItem.Json

$formData = ConvertFrom-Json $formJson

$formItem = New-Item -Path ``"master:\sitecore\Forms\$($formData.Name)" -ItemType $($fieldTemplates.Form)

$formItemPath = $formItem.Paths.FullPath

$formProperties = @{ }

Set-FormProperties $formProperties $formData

Update-NewItem $formItem $formProperties

Invoke-ProcessElements $formData.elements $formItemPath

The above code starts by asking the user for the path to a Sitecore item containing the JSON to be imported; the template for this item is included in the package. Once the JSON is read and converted, I immediately read the root level object. It's a known expectation that it's a regular item with an elements array. Import the first item, and then kick off a recursive execution to process the elements thereafter. Each field type has a processor method that will explicitly map values into the appropriate fields. These processor methods are separated out so they can be easily adjusted. Additionally, the processors are smart enough to not alter a value that isn't specified in the JSON. This means that it is only necessary to set the values you need, and all other values will just take on the standard values for their template.

There are some ancillary functions included with the package which are leveraged for updating the items as they are created, as well as ensuring that the values in the JSON are of the expected type. Lastly, there are some extra methods for handling the special fields (e.g. Drop Down Lists), allowing for both dynamic datasource drive options and static options.

Hop on over to the GitHub repo to take a look at the scripts and to download the package. I hope this helps get some of those longer forms out of the way a little bit quicker.