gmst-forms v1.1.9-brain
GMST Forms
Overview
GMST Forms (<gmst-form>
) is a WebComponent library built using the tools provided by the gmwc
toolkit. The library contains components that without configuration, can create a working form, and can be extended to add any custom functionality needed. By default all forms will be accessibility compliant.
Building a form starts with including a gmst-form
element on the page and nesting form fields like gmst-form-input
with some attributes underneath. All form fields have functionality to translate labels, error messages and placeholders (soon). Some form fields also include a way to perform multiple field level validations at a time.
In the future, functionality will be added to allow for forms to be built purely off of a configuration object or a simple markup language based on the components themselves.
Components
Form (gmst-form)
<gmst-form>
<div slot="form">
...
</div>
<div slot="after-submission">
...
</div>
</gmst-form>
The form component is a wrapper component for a form built using the library. The component provides a few different ways to handle form submission and blocks submissions altogether if there are any validation errors.
There are two useable slots in the gmst-form
component. form
is used to place all form elements into, and after-submission
is an area to place content that will be displayed after a submission is successful. Usually the after-submission
slot will be used for a thank you page/message.
Ways to Handle Submissions (WIP)
- Form submissions can be done using the default form submission. (This will be an attribute that is passed through)
- Write a
window.handleFormSubmit
function that recieves form data and submits it in some way. - Extend the GMSTForm component and overwrite the default
handleSubmit()
method.
Form Element (GMSTFormElement)
GMSTFormElement is the "base component class", meaning all of the form field elements are extended from it. GMSTFormElement provides a lot of the base functionality incluing validations, hide/show, rendering and more.
Each element that is extended off of GMSTFormElement will start similarly. Below is the gmst-form-input
component, which is a good place to start from.
// Import GMSTFormElement from wherever it is located
import { GMSTFormElement } from '../gmst-form-element/gmst-form-element';
export class GMSTFormInput extends GMSTFormElement {
constructor(self) {
self = super(self);
// Components extended off of GMSTFormElement begin with a configuration.
self.configuration = {
// These three key/values are needed for the element to render properly.
// `fieldType` is the HTML Element type of the field (e.g. input, select)
fieldType: 'input',
// `labelElementType` is the HTML Element type of the label (e.g. label, legend)
labelElementType: 'label',
// The template name is the HTML template used for the custom element in camelcase.
templateName: 'gmstFormInput', // The actual file name is `gmst-form-input.html`
// When validation is necessary for a form field validation happens on the event specified
// in `validateOnEvent` and validation errors are cleared when the configured `clearValidationOnEvent` is fired.
clearValidationOnEvent: 'input',
validateOnEvent: 'blur'
};
return self;
}
}
Checkbox (gmst-form-checkbox)
<gmst-form-checkbox
name="optIn"
element-id="optInEmail"
label="optIn"
value="optIn"
business-rules='[{
"effect": "unCheckField",
"event": "click",
"fieldIds": ["fieldID"]
}]'>
</gmst-form-checkbox>
The checkbox component creates an HTML structure with an i18n label and a checkbox. (Validation soon). Added Business Rule will uncheck Field with given ID
Input (gmst-form-input)
<gmst-form-input
type="text"
name="firstName"
element-id="firstName"
label="firstName"
placeholder="i18nLabel"
validations="required,otherValidation">
</gmst-form-input>
The input component creates an HTML structure with an i18n label, an input and space for validation messages to be displayed. The field is validated each time the input element fires an onblur
event and displays an error message when necessary.
Google Address Autocomplete (gmst-form-google-address)
<gmst-form-google-address
autocomplete-elements='{
"street_number": "address",
"route": "address",
"locality": "city",
"administrative_area_level_1": "province",
"postal_code": "postalCode"
}'
type="text"
name="salesLead.address.address"
element-id="address"
label="address"
validations="required">
gmst-form-google-address
is a component extended from gmst-form-input
to provide Google address autocomplete functionality to a form.
Specific to gmst-form-google-address
is the autocomplete-elements
attribute that is used to fill in address information into other form elements. The value for this attribute is a JSON formatted Javascript object where each key is a portion of an address provided by Google and the value is the element-id
of a form element to fill the information into. If multiple keys share an element-id
the information is appended.
Radio (gmst-form-radio)
<gmst-form-radio
options='[{"value": "email", "label": "email"}, {"value": "phone", "label": "phone"}]' name="preferredContact"
title="preferredContact">
</gmst-form-radio>
The radio component creates an HTML structure for a radio button fieldset with a label. Options are passed in as a JSON structured array, each radio button contains an i18n label.
Select (gmst-form-select)
<gmst-form-select
options='[{"value": "Request for Information", "label": "ownershipExperience"}, {"value": "Service", "label": "serviceExperience", "selected": true}]'
element-id="questionType"
name="questionType"
label="questionType">
</gmst-form-select>
The select component creates an HTML structure for a select with a label. The select options are passed in as a JSON structured array, where each select has an i18n label, one option can be preselelected.
Additional functionality can be found in the section on field attributes.
Text Area (gmst-form-text-area)
<gmst-form-text-area
element-id="comments"
label="comments"
placeholder="i18nLabel">
</gmst-form-text-area>
The select component creates an HTML structure for a textarea with a label.
Component Attributes
The following component attributes are used on all components (except gmst-form
) unless specified otherwise.
element-id
The element-id
attribute is used to add a unique id
to a form field (e.g. select
, input
). A for
attribute is also added to that form element's corresponding label
.
element-id
is also used to select the form custom elements as well. This can be necessary when adding functionality that requires a references to other custom elements.
label
The label
attribute is used to add a label to a form field. The value is the key to the string you want in the current I18n
collection of labels.
name
The name
attribute is used to provide a name
to a form field, this is used during submission.
options
The options
attribute is used on components that have multiple items to choose from. options
is currently only used with gmst-form-radio
and gmst-form-select
. The value of options
is a JSON array of objects, each individual option has a few different values to use.
In gmst-form-radio
, each object is an individual radio button.
In gmst-form-select
, each object is an individual select
option.
Options for options
Each object should contain a value
and a label
.
Optionally an option can be preselected by providing "selected": true
Specific to gmst-form-select
Currently there are a few features specific to gmst-form-select
.
hideFields
/showFields
- A JSON array of fields (a component's `element-id) to be hidden/shown on select.
addFieldValidations
/removeFieldValidations
- A JSON array of objects used to add and remove field validations on select. Each object contains an elementId
and an array of validations
.
validations
The validations
attribute is used to set validations for a form element. If a field is hidden all validations will be disabled.
The value expected is a comma separated list of validations. This can include validations provided in this library or extended validations.
value
The value
attribute is used to add a preset value can be passed into a few different form elements. This is particularly useful for hidden gmst-form-input
s.
Extending Base Functionality
export class CustomGMFormInput extends GMFormInput {
...
extendedFunctionality() {
...
}
...
}
Each component includes an extendedFunctionality()
method that is ran at the end of a components render()
method.
A few components include methods like addInputEventListener()
where the default validation logic is added, these can be overwritten as well.
Validation
// required - returns 'Required' when value is empty
// testValue - returns 'Must be "Test"' when the value is not 'Test'
let value = '';
let validationResult = validate(['required', 'testValue'], value);
// -> 'Required'
let value = 'T';
let validationResult = validate(['required', 'testValue'], value);
// -> 'Must be "Test"'
let value = 'Test';
let validationResult = validate(['required', 'testValue'], value);
// -> undefined
Included in the library is a simple way of doing form validations for single form field. A comma separated list of validations are passed in as an attribute on custom elements like gmst-form-input
and ran after a specific event is triggered.
Extending Validations
Each validation follows the same structure, return an error message when there is an error, otherwise return undefined
.
Below is an example of extending validation functionality.
import { validate, allValidations } from 'gmst-forms'
const newValidation = (value) => value === 'New' ? undefined : 'Must be "New"';
allValidations.newValidation = newValidation;
validate(['newValidation'], 'New'); // returns undefined;
Utilities
There are a few utilities provided by the library that can be used to extend the functionality of the form.
getFormData(element)
- Given an element will return the nearest form element's data. The output provided is the same as jQuery'sserializeArray()
.- ...
Translations
There are a few places where components allow for translations using the gmwc-i18n
library:
- Form field - Each form field has a
label
attribute where a translation key is provided. - When a form field has an
options
attribute there is alabel
key in each object where a translation key is provided. - Validation Errors - Each validation rule will return a translation key or a string.
Future Features and Ideas
Optional HTML Options
Currently on components that have multiple field options, like gmst-form-select
only accept an array of objects in JSON format. In the future it might be a good idea to make writing JSON optional and stick to HTML markup. To do this each option
will be a child element of the component.
Example
<gmst-form-select ...>
<gmst-form-option
value="Example Option"
label="exampleLabel">
</gmst-form-option>
</gmst-form-select>
Configuraton Based Form
Currently Global Forms is able to build out a fully functioning form based off of a large configuration object. This library can be extended to match current Global Forms functionality and even improve it. To do this a configuration tool will be created that allows for creation of complex forms that can be imported by the gmst-form
component.
Given a configuration object gmst-form
will render a form based on the configuration without any additional steps.
Form Markup
As an alternative to generating a configuration object, since these are custom elements, it is possible that a form can be built purely from some HTML markup passed onto a page. Form configurations can be hosted externally and can be pulled onto the page using DataProvider
(or other tools) and rendered using all of the elements provided by the library.
Examples
Contact Form
This is the form included in index.html
.
<gm-form>
<div slot="form" class="gm-form">
<gmst-form-select
options='[{"value": "Request for Information", "label": "ownershipExperience"}, {"value": "Service", "label": "serviceExperience", "selected": true}]'
element-id="questionType"
name="questionType"
label="questionType"></gmst-form-select>
<gmst-form-input type="text" name="firstName" element-id="firstName" label="firstName"></gmst-form-input>
<gmst-form-input type="text" name="lastName" element-id="lastName" label="lastName" validations="required,testValue"></gmst-form-input>
<gmst-form-input type="text" name="postalCode" element-id="postalCode" label="postalCode"></gmst-form-input>
<!-- <gmst-postalcode class="container-fluid"></gmst-postalcode> -->
<gmst-form-input type="email" name="emailAddress" element-id="emailAddress" label="emailAddress"></gmst-form-input>
<gmst-form-input type="tel" name="phoneNumber" element-id="phoneNumber" label="phoneNumber"></gmst-form-input>
<gmst-form-input type="text" name="vin" element-id="vin" label="vin"></gmst-form-input>
<gmst-form-input type="text" name="model" element-id="model" label="model"></gmst-form-input>
<gmst-form-input type="text" name="comments" element-id="comments" label="comments"></gmst-form-input>
<gmst-form-radio options='[{"value": "email", "label": "email"}, {"value": "phone", "label": "phone"}]' name="preferredContact" title="preferredContact"></gmst-form-radio>
<gmst-form-text-area element-id="comments" label="comments"></gmst-form-text-area>
<gmst-form-checkbox name="optIn" id="optInEmail" label="optIn" value="optIn"></gmst-form-checkbox>
<button type="submit">Submit</button>
</div>
</gm-form>
6 years ago