JSON Form Definition

I work in the area of web development called web content management or WCM for short. One of the problems that often needs resolved is an easy and repeatable way to define forms through which WCM authors use to create content.

An often first step in the creation of any new feature is defining a form which may include text fields, checkboxes, radio options, specialized text fields such as urls, dates, or paths to other pieces of content. On top of this having a multivalued list of any of these fields is also common such as a list of links each with a corresponding checkbox to determine if the link opens in a new tab or not. These forms can become quite complex and having an easy way to define them speeds up development of new features.

It occurred to me that using JSON as a means of defining a form would allow a developer to define what JSON they expect back from the form after the user interacts with it. This is similar to the idea behind GraphQL, tell the API what JSON you want to see and then it gives it to you. I have created an example of what this form-definition JSON might look like:
{
   "firstName":"",
   "isDeveloper":true,
   "height":0
}
In this example we have a text field with the name of "firstName", a checkbox with the name "isDeveloper", and a number field with the name "height". However what if we wanted to add default values to these fields? You might already see what I am seeing:
{
   "firstName":"Default first name",
   "isDeveloper":true,
   "height":60
}
The default value of each form field can just be the value of the field in the JSON. What if we wanted the user of this form to be able to define a list of contacts? Maybe with a "+" button in the form to allow them to add new fields to a list?
{
   "firstName":"Default first name",
   "isDeveloper":true,
   "height":60,
   "contacts":[
      ""
   ]
}
We add an array value to the JSON which represents a multi valued form element. In this way the user could add a list text fields, each of which represents a contact. However what if we want each contact to have a name and an email?
{
   "firstName":"Default first name",
   "isDeveloper":true,
   "height":60,
   "contacts":[
      {
         "firstName":"",
         "email":""
      }
   ]
}
Now we put an object in the array instead of a simple string field. This means that each multi valued element within the contact list has two associated values, "firstName" and "email".

However what if for one of our fields we want to explicitly specify an associated label, validation that should be applied, or a placeholder value?
{
   "firstName":{
      "type":"",
      "defaultValue":"Default first name",
      "placeholder":"Example Place holder"
   },
   "isDeveloper":{
      "type":true,
      "label":"Are you a developer?"
   },
   "height":60,
   "contacts":[
      {
         "firstName":"",
         "email":{
            "type":"",
            "validation":"email"
         }
      }
   ]
}
Now the objects can either represent a set of fields for the form or if they have the "type" property they represent a single field of the given type. This provides an entry point for defining things such as validation, labels, and other data that the form may need for the field. Notice that the default value for the field is no longer passed in the string itself but is provided in a "defaultValue" property. This is so that we can reserve the use of the "type" property as you will see next.

Not all strings are created equal. What if we wanted a string field that represents a path to another piece of data in the WCM system or maybe a date field?
{
   "firstName":{
      "type":"",
      "defaultValue":"Default first name",
      "placeholder":"Example Place holder"
   },
   "birthDate":{
      "type":"date"
   },
   "homePage":{
      "type":"path"
   },
   "isDeveloper":{
      "type":true,
      "label":"Are you a developer?"
   },
   "height":60,
   "contacts":[
      {
         "firstName":"",
         "email":{
            "type":"",
            "validation":"email"
         }
      }
   ]
}
Now custom dialog field types can be specified that store the resulting value as a string, but have a custom user interaction for determining that string. Now what would the JSON that the form generates look like? Well it looks almost exactly the same, except wherever you see the "type" field in the JSON that object is replaced with a value of the given type:
{
   "firstName":"Joe Smith",
   "birthDate":"5/26/1983",
   "homePage":"/some/example/path/that/specifies/joe/smiths/homepage",
   "isDeveloper":true,
   "height":71,
   "contacts":[
      {
         "firstName":"Steve Adams",
         "email":"steve.adams@example.com"
      },
      {
         "firstName":"Bob Greene",
         "email":"bobgreen12@example.com"
      }
   ]
}
When the user submits the form this JSON can then be stored in a database or in your WCM system however you would like.

Now I just need to create the JavaScript library that creates the form and then generates the JSON based upon the form. I might do that has a side project in the coming months if time allows. I know this would be useful in some of the projects that I have going on.

Comments

Popular Articles

The Vanilla Javascript Component Pattern

The Sunless Citadel: A D&D 5e Session Report

Getting Started with Harp