Skip to content

Instantly share code, notes, and snippets.

@dennisat
Last active July 16, 2020 17:48
Show Gist options
  • Save dennisat/336fb1167d49473a876b235e0de1c29a to your computer and use it in GitHub Desktop.
Save dennisat/336fb1167d49473a876b235e0de1c29a to your computer and use it in GitHub Desktop.
Clubform Builder Documentation for DGWs

Clubform Builder Documentation for DGWs

Builder Usage

The clubform builder is a text editor that helps build the JSON to define a form. A forms look/style is defined by it's layout type. (Right now, there is only one)

Layout Style Description
Traditional How clubforms looked and operated before the builder was made.
Traditional JSON Example (No buttons)
{
  "instructions": "",
  "linkToGCC": false,
  "form": [
    {
      "component": "InputWrapper",
      "label": "First Name",
      "children": [
        {
          "component": "GenericInput",
          "mapsTo": "firstName",
          "isRequired": true
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "Last Name",
      "children": [
        {
          "component": "GenericInput",
          "mapsTo": "lastName",
          "isRequired": true
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "Address",
      "children": [
        {
          "component": "GenericInput",
          "mapsTo": "address.address1",
          "isRequired": false
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "",
      "children": [
        {
          "component": "GenericInput",
          "mapsTo": "address.address2",
          "isRequired": false
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "City",
      "children": [
        {
          "component": "GenericInput",
          "mapsTo": "address.city",
          "isRequired": false
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "State",
      "children": [
        {
          "component": "StateSelect",
          "defaultState": "PA",
          "isRequired": false
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "Zip",
      "children": [
        {
          "component": "GenericInput",
          "mapsTo": "address.zip",
          "validateNumeric": true,
          "isRequired": false
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "Phone Number",
      "children": [
        {
          "component": "PhoneInput",
          "mapsTo": "mobilePhone",
          "isRequired": true
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "Email",
      "children": [
        {
          "component": "EmailInput",
          "mapsTo": "email",
          "isRequired": true
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "Source",
      "children": [
        {
          "component": "SourceSelect",
          "promptOption": "How did you hear about us?",
          "isRequired": true
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "Liability Waiver",
      "align": "top",
      "notes": true,
      "errorType": "waiver",
      "children": [
        {
          "component": "GuestWaiver"
        }
      ]
    }
  ]
}
Traditional JSON Example (Multi-button)
{
  "instructions": "Please fill out this form",
  "linkToGCC": false,
  "multiButton": {
    "title": "Welcome to Gold's Gym!",
    "instructions": "Select an option below to continue."
  },
  "newGuest": {
    "title": "Welcome to Gold's Gym!",
    "label": "New Guest",
    "instructions": "This is your first time at the club or you are here to ask about a membership."
  },
  "paidPass": {
    "title": "You selected Paid Pass",
    "label": "Paid Pass",
    "instructions": "You are here from out of town or are working out for the day on a paid pass.",
    "paidPassMemberId": 110336789
  },
  "paidPassV2": {
    "title": "You selected Paid Pass",
    "label": "Paid Pass",
    "instructions": "You are here from out of town or are working out for the day on a paid pass.",
    "paidPassMemberId": 110336789
  },
  "returnGuest": {
    "title": "You selected Returning Guest",
    "label": "Returning Guest",
    "instructions": "You have been here before, or you have an active guest pass."
  },
  "vipGuest": {
    "title": "You selected VIP Guest",
    "label": "VIP Guest",
    "instructions": "You are a true VIP."
  },
  "student": {
    "title": "You selected Student Check In",
    "label": "Student Check In",
    "instructions": "You're a student and this is your first time checking in."
  },
  "form": [
    {
      "component": "InputWrapper",
      "label": "First Name",
      "children": [
        {
          "component": "GenericInput",
          "mapsTo": "firstName",
          "isRequired": true
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "Last Name",
      "children": [
        {
          "component": "GenericInput",
          "mapsTo": "lastName",
          "isRequired": true
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "Employer",
      "children": [
        {
          "component": "GenericInput",
          "mapsTo": "employer",
          "isRequired": true,
          "text": "<i style=\"color:red;display:block;width:300px;\">Providing your employer will help us determine if you have a discounted membership option available through our corporate wellness program.</i>"
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "Email",
      "children": [
        {
          "component": "EmailInput",
          "mapsTo": "email",
          "isRequired": "emailOrMobilePhone"
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "Phone",
      "children": [
        {
          "component": "PhoneInput",
          "mapsTo": "mobilePhone",
          "isRequired": "emailOrMobilePhone"
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "Gender",
      "children": [
        {
          "component": "GenericSelect",
          "mapsTo": "gender",
          "options": [{"M": "Male"}, {"F": "Female"}],
          "isRequired": true
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "Source",
      "children": [
        {
          "component": "SourceSelect",
          "promptOption": "How did you hear about us?",
          "isRequired": true
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "State",
      "children": [
        {
          "component": "StateSelect",
          "defaultState": "PA",
          "isRequired": true
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "Goals",
      "align": "top",
      "children": [
        {
          "component": "CheckboxGroup",
          "mapsTo": "goals",
          "options": ["Lose weight", "Stress management", "Build muscle and core strength"]
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "Appointment",
      "align": "top",
      "children": [
        {
          "component": "RadioGroup",
          "mapsTo": "appointment",
          "options": ["I have an appointment", "I do not have an appointment"]
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "Interests Group Example",
      "align": "top",
      "children": [
        {
          "component": "InterestsGroup"
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "Notes",
      "align": "top",
      "children": [
        {
          "component": "GenericTextarea",
          "mapsTo": "notes",
          "rows": 6
        }
      ]
    },
    {
      "component": "InputWrapper",
      "label": "Guest Waiver",
      "align": "top",
      "notes": true,
      "errorType": "waiver",
      "children": [
        {
          "component": "GuestWaiver"
        }
      ]
    }
  ]
}

Dynamic Variables

Dynamic variables allow you to inject data into text that is pulled into the form via <%= %> tags.

Location

<%= location %>: Replaced with club location name.

Component Details

* Denotes required key

Title

The "Header" of the form.

  • title: Any text (default "Thank you for visiting {location}"). Will be overriden by Multi-Button: New Guest Title if exists.
Instructions

Instruction text that will be placed under the form title.

  • instructions*: Any text
Guest Courtesy Card

Specifies if the DGW has inputs that should correlate with a Guest Courtesy Card.

  • linkToGCC: Can be true or false (default false)
Multi-Button

Specifies if the DGW begins as a multi-button form

  • multiButton: Can be true, an object with properties, or false (default false)
Multi-Button: Override Defaults (multiButton)

Overrides the title and/or instructions of the mutli-button screen of a form.

  • title: String defining the "Header" of the visible page (default "Welcome to {club} - {location}")
  • instructions: String defining the instructions text that goes above the buttons
Multi-Button: New Guest (newGuest)

Button labeled "New Guest" that takes the user straight into the DGW. MUST have Multi-button set to true.

  • title: String defining the "Header" of the visible page (default "Thank you for visiting {location}")
  • label: String defining the button's label (default "New Guest")
  • instructions: String defining the instructions text that goes below the button (see example at bottom)
Multi-Button: Return Guest (returnGuest)

Button labeled "Returning Guest" that takes the user to a "search by email or phone" before going into the DGW. MUST have Multi-button set to true.

  • title: String defining the "Header" of the visible page (default "Returning Guest")
  • label: String defining the button's label (default "Returning Guest")
  • instructions: String defining the instructions text that goes below the button
Multi-Button: VIP Guest (vipGuest)

Button labeled "VIP Guest" that takes the user to a "search by email or phone" before going into the DGW. MUST have Multi-button set to true.

  • title: String defining the "Header" of the visible page (default "Gold Member Guest Registration")
  • label: String defining the button's label (default "Gold Member Guest")
  • instructions: String defining the instructions text that goes below the button
Multi-Button: Paid Pass (paidPass)

Button labeled "Paid Pass" that takes the user to a confirmation page that they are using a paid pass before going into the DGW. MUST have Multi-button set to true.

  • title: String defining the "Header" of the visible page (default "Paid Pass")
  • label: String defining the button's label (default "Paid Pass")
  • instructions: String defining the instructions text that goes below the button (see example at bottom)
  • paidPassMemberId*: Club member id for the paid pass account
Form Wrapper

Must be placed around the entire form structure

  • form*: An array housing the form structure
Input Wrapper

Must be placed around inputs that are not labelled as composites

  • component*: Must be "InputWrapper"
  • label: Any text, will be the label for the input
  • align: Can be set to "top", which will vertically align the label to the top (align middle by default)
  • errorType: Should be set to "waiver" for waivers
  • notes: Can be true or false, and toggles if the notes class is applied (default false)
  • children*: An array housing the input
Generic Input
  • component*: Must be "GenericInput"
  • mapsTo*: Suggested to be "firstName", "lastName", "address.address1", "address.address2", "address.city", "address.zip", "employer" or "guestOfMember"
  • isRequired: Can be true or false (default false, however, "firstName" and "lastName" are forced to true)
  • linkToGCC: Can be true or false, toggling whether an input with the same name (mapsTo) exists in a Guest Courtesy Card (default false)
  • text: String or element definition of text that can be placed below the input
  • showOnAppointmentsForm: Can be true or false, toggling whether an input shows on the form when a user selects the "I have an appointment option" (see 'Showing fields on the "Appointment" form' section for more details)
Email Input
  • component*: Must be "EmailInput"
  • mapsTo*: Suggested to be "email"
  • isRequired: Can be true, false or "emailOrMobilePhone" (default false)
  • linkToGCC: Can be true or false, toggling whether an input with the same name (mapsTo) exists in a Guest Courtesy Card (default false)
  • showOnAppointmentsForm: Can be true or false, toggling whether an input shows on the form when a user selects the "I have an appointment option" (see 'Showing fields on the "Appointment" form' section for more details)
Phone Input
  • component*: Must be "PhoneInput"
  • mapsTo*: Suggested to be "mobilePhone", "workPhone" or "homePhone"
  • isRequired: Can be true, false or, if mapsTo is "mobilePhone", "emailOrMobilePhone" (default false)
  • linkToGCC: Can be true or false, toggling whether an input with the same name (mapsTo) exists in a Guest Courtesy Card (default false)
  • showOnAppointmentsForm: Can be true or false, toggling whether an input shows on the form when a user selects the "I have an appointment option" (see 'Showing fields on the "Appointment" form' section for more details)
Generic Select
  • component*: Must be "GenericSelect"
  • mapsTo*: Suggested to be "gender"
  • options*: Array of strings (ex: ["Uno", "Dos"]) or objects (ex: [{"M": "Male"}, {"F": "Female"}]). For strings, both the saved value and the display value are equal to the string. For objects, the saved value is the key, and the display value is the value.
  • promptOption: First option to be displayed, and acts as instructions (will not save data if nothing else is selected)
  • defaultValue: Can be set to an option value, if a default option should be selected (default none)
  • isRequired: Can be true or false (default false)
  • linkToGCC: Can be true or false, toggling whether an input with the same name (mapsTo) exists in a Guest Courtesy Card (default false)
  • showOnAppointmentsForm: Can be true or false, toggling whether an input shows on the form when a user selects the "I have an appointment option" (see 'Showing fields on the "Appointment" form' section for more details)
Employer Select
  • component*: Must be "EmployerSelect"
  • mapsTo: Un-editable (default "employer")
  • promptOption: First option to be displayed, and acts as instructions (will not save data if nothing else is selected)
  • defaultValue: Can be set to an option value, if a default option should be selected (default none)
  • isRequired: Can be true or false (default false)
  • linkToGCC: Can be true or false, toggling whether an input with the same name (mapsTo) exists in a Guest Courtesy Card (default false)
  • showOnAppointmentsForm: Can be true or false, toggling whether an input shows on the form when a user selects the "I have an appointment option" (see 'Showing fields on the "Appointment" form' section for more details)
Source Select
  • component*: Must be "SourceSelect"
  • mapsTo*: Un-editable (default "source")
  • promptOption: First option to be displayed, and acts as instructions (will not save data if nothing else is selected)
  • defaultValue: Can be set to an option value, if a default option should be selected (default none)
  • isRequired: Can be true or false (default false)
  • linkToGCC: Can be true or false, toggling whether an input with the same name (mapsTo) exists in a Guest Courtesy Card (default false)
  • showOnAppointmentsForm: Can be true or false, toggling whether an input shows on the form when a user selects the "I have an appointment option" (see 'Showing fields on the "Appointment" form' section for more details)
State Select
  • component*: Must Be "StateSelect"
  • defaultState: Can be set to a state ISO code, if a default state should be selected (default none)
  • isRequired: Can be true or false (default false)
  • linkToGCC: Can be true or false, toggling whether an input with the same name (mapsTo) exists in a Guest Courtesy Card (default false)
  • showOnAppointmentsForm: Can be true or false, toggling whether an input shows on the form when a user selects the "I have an appointment option"
Country Select

Used in conjunction with StateCompositeSelect and ZipCompositeSelect to enable Canadian address support. Defaults to "US"

  • component*: Must Be "CountrySelect"
  • isRequired: Can be true or false (default false)
  • linkToGCC: Can be true or false, toggling whether an input with the same name (mapsTo) exists in a Guest Courtesy Card (default false)
  • showOnAppointmentsForm: Can be true or false, toggling whether an input shows on the form when a user selects the "I have an appointment option" (see 'Showing fields on the "Appointment" form' section for more details)
State Composite Select

Used in conjunction with CountrySelect and ZipCompositeSelect to enable Canadian address support. When "CA" is selected via CountrySelect, "State" label will change to "Province" and values will be updated with Canadian provinces.

  • component*: Must Be "StateCompositeSelect"
  • defaultState: Can be set to a state ISO code, if a default state should be selected (default none)
  • isRequired: Can be true or false (default false)
  • linkToGCC: Can be true or false, toggling whether an input with the same name (mapsTo) exists in a Guest Courtesy Card (default false)
  • showOnAppointmentsForm: Can be true or false, toggling whether an input shows on the form when a user selects the "I have an appointment option" (see 'Showing fields on the "Appointment" form' section for more details) Note: Composite inputs do not use a InputWrapper. The label is automatically generated.
Zip Composite Select

Used in conjunction with CountrySelect and StateCompositeSelect to enable Canadian address support. When "CA" is selected via CountrySelect, the "Zip" label will change to "Postal Code," and field will accept letters for Canadian postal codes.

  • component*: Must Be "ZipCompositeSelect"
  • isRequired: Can be true or false (default false)
  • linkToGCC: Can be true or false, toggling whether an input with the same name (mapsTo) exists in a Guest Courtesy Card (default false)
  • showOnAppointmentsForm: Can be true or false, toggling whether an input shows on the form when a user selects the "I have an appointment option" (see 'Showing fields on the "Appointment" form' section for more details) Note: Composite inputs do not use a InputWrapper. The label is automatically generated.
Birthdate Select
  • component*: Must Be "BirthdateSelect"
  • isRequired: Can be true or false (default false)
  • linkToGCC: Can be true or false, toggling whether an input with the same name (mapsTo) exists in a Guest Courtesy Card (default false)
  • showOnAppointmentsForm: Can be true or false, toggling whether an input shows on the form when a user selects the "I have an appointment option" (see 'Showing fields on the "Appointment" form' section for more details)
Checkbox Group
  • component*: Must be "CheckboxGroup"
  • mapsTo*: Suggested to be "goals", "reasonJoiningGym", "daysOfWeek", "timeOfDay", "seriousAboutStarting", "smsOptIn" or "emailOptIn"
  • options*: Checkbox options
  • orientVertical: Can be true or false, determines if the options should be in a vertical list, or can be horizontally aligned (default true)
  • defaultCheckedIndex: Option to be checked by default, starting at 0 (default none)
  • isRequired: Can be true or false (default false)
  • linkToGCC: Can be true or false, toggling whether an input with the same name (mapsTo) exists in a Guest Courtesy Card (default false)
  • showOnAppointmentsForm: Can be true or false, toggling whether an input shows on the form when a user selects the "I have an appointment option" (see 'Showing fields on the "Appointment" form' section for more details)
Radio Group
  • component*: Must be "RadioGroup"
  • mapsTo*: Suggested to be "married", "children", "currentlyExercise" or "appointment"
  • options*: Radio options
  • orientVertical: Can be true or false, determines if the options should be in a vertical list, or can be horizontally aligned (default true)
  • defaultCheckedIndex: Option to be checked by default, starting at 0 (default none)
  • isRequired: Can be true or false (default false)
  • linkToGCC: Can be true or false, toggling whether an input with the same name (mapsTo) exists in a Guest Courtesy Card (default false)
  • showOnAppointmentsForm: Can be true or false, toggling whether an input shows on the form when a user selects the "I have an appointment option" (see 'Showing fields on the "Appointment" form' section for more details)
Interests Group
  • component*: Must be "InterestsGroup"
  • orientVertical: Can be true or false, determines if the options should be in a vertical list, or can be horizontally aligned (default true)
  • isRequired: Can be true or false (default false)
  • linkToGCC: Can be true or false, toggling whether an input with the same name (mapsTo) exists in a Guest Courtesy Card (default false)
  • showOnAppointmentsForm: Can be true or false, toggling whether an input shows on the form when a user selects the "I have an appointment option" (see 'Showing fields on the "Appointment" form' section for more details)
Generic Textarea
  • component*: Must be "GenericTextarea"
  • mapsTo*: Suggested to be "notes" (if not appending notes)
  • rows: How many rows tall the textarea should be (default 5)
  • columns: How many columns wide the textarea should be (default 100% of parent's width)
  • defaultValue: Pre-populates the textarea with modifiable text
  • isRequired: Can be true or false (default false)
  • linkToGCC: Can be true or false, toggling whether an input with the same name (mapsTo) exists in a Guest Courtesy Card (default false)
  • showOnAppointmentsForm: Can be true or false, toggling whether an input shows on the form when a user selects the "I have an appointment option" (see 'Showing fields on the "Appointment" form' section for more details)
Guest Waiver
  • component*: Must be "GuestWaiver"
  • noScroll: Can be true or false, and toggles scrolling to the bottom is required for acceptance (default false)
  • Note that the input wrapper must have the errorType set to "waiver", and notes should be true. It's also suggested align be "top"
Generic Hidden
  • component*: Must be "HiddenGeneric"
  • mapsTo*: Suggested to be "notes"
  • linkToGCC: Can be true or false, toggling whether an input with the same name (mapsTo) exists in a Guest Courtesy Card (default false)
  • showOnAppointmentsForm: Can be true or false, toggling whether an input shows on the form when a user selects the "I have an appointment option" (see 'Showing fields on the "Appointment" form' section for more details)

Recommended Creation of an Opt-in Box

{
  "component": "InputWrapper",
  "label": "SMS Opt-in",
  "align": "top",
  "notes": true,
  "children": [
    {
      "component": "CheckboxGroup",
      "mapsTo": "smsOptIn",
      "defaultCheckedIndex": 0,
      "options": [
        "I agree to recieve SMS."
      ]
    }
  ]
}

Appending to Notes

Requirements:

  • A hidden field using GenericHidden, which will most likely map to "notes" unless doing something advanced
  • At least one field with the "appendTo" property defined

You can append the responses to other inputs into a hidden field, which will hold the data for from submission. Any field can be specified to append it's response into a hidden field using the appendTo property. The markup may look like this:

...
{
  "component": "InputWrapper",
  "label": "Goals",
  "align": "top",
  "children": [
    {
      "component": "CheckboxGroup",
      "mapsTo": "goals",
      "options": ["Lose weight", "Stress management", "Build muscle and core strength"],
      "appendTo": {
        "field": "notes",
        "label": "PT Goals"
      }
    }
  ]
},
{
  "component": "InputWrapper",
  "children": [
    {
      "component": "GenericHidden",
      "mapsTo": "notes"
    }
  ]
}
...

Explanation of appendTo: The field describes the hidden field's map to value that the responses will be appended to, and is required. The label will describe the response in the submission, and is also required. The output for notes for this field will look like:

PT Goals: Lose weight, Stress management.

Explanation of the hidden field: Since the data will be stored in a hidden field, a hidden field must be included in the form. This field will not be shown on the form itself. It is suggested that the mapsTo of the hidden field always be "notes".

Restrictions:

  • Birthdate Select is not supported
  • Goals is already appended to notes by default, so do not use append to on a field mapped to "goals"

Advanced Tip:

  • If you need to have both an appended to notes field, and visible notes, set the mapsTo of the visible notes to "visibleNotes", and add appendTo so that the response will be appended to the hidden notes field.

Admin Setup

Club General Settings:

  • Domain Prefix: Defines the location at which the clubform can be accessed
  • Logo Image File: Specifies the logo to use on the clubform
  • Theme Name: Specifies what theme will be used (mainly color configuration)
  • Liability / Waiver Text: Text that will populate the waiver text

Location General Settings:

  • Show Toured By on Digital Guest Waiver: Toggles the displaying of and requirement of "Toured By"
  • Show Signature on Digital Guest Waiver: Toggles the displaying of and requirement of "Signature"

Showing fields on the "Appointment" form

When the appointments feature is enabled and a user indicates they have an appointment the form only displays certain fields by default:

(The list below is the HTML input name for each field)

  • firstName
  • lastName
  • smsOptIn
  • emailOptIn
  • waiverAgree
  • waiver
  • mobilePhone
  • homePhone
  • workPhone
  • signatureData
  • email

To include additional fields you can set the showOnAppointmentsForm property to true for individual components.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment