Forms

Form-Validation

FlexCss contains a comprehensive form library with a solid JavaScript plugin that utilises HTML5 Form-Validation. FlexCss.Form overwrites the default behaviour of the browser to support a consistent UI across all browsers and adds support for custom validators and inline validation (on blur and optional in realtime with keyup).


Features

  • Plugin-In replacement for HTML5-Form-Validation
    • Zero-Configuration for build-in input-types, patterns and required fields
    • Fully I18n support trough build-in Browser-Support
  • Standalone just ~14kB compressed
  • Inline-Validation blur or realtime
  • Custom-Validation/Validators
  • Submitting and Validating a form via XHR (json or form encoded)
  • Beautiful validation UI (Tooltip or inline)
  • Event System

Getting started

Initialize the plugin for all forms on a page with the following line:

FlexCss.Form.init('form', optionalOptions);

The first param form may be a selector defined by Document.querySelector(). The second one allows to overwrite defaultOptions for each form. All Options may be set trough a data attribute.

{
    // if true creates tooltips above element, uses FlexCss Tooltips
    createTooltips: true,
    // if true appends error message after input element
    appendError: false,
    // type of ajax submit
    ajaxSubmitType: 'POST',
    // json content type if ajax method is set to json
    ajaxJsonContentType: 'application/json; charset=utf-8',
    // allow inline validation
    inlineValidation: true,
    // validate in realtime (on `input` event)
    realtime: true,
    // timeout when realtime event should be captured
    realtimeTimeout: 250,
    // formatting method for an error
    formatErrorTooltip: (error) => {
        return '<i class="icon-attention"></i> ' + error;
    },
    // the class that will be put on the element to mark it failed validation
    inputErrorClass: 'invalid',
    // the container class for error messages below an element
    containerErrorClass: 'form-error',
    // additional options for fetch
    fetchOptions: {
        credentials: 'include'
    },
    // the container for tooltips
    tooltipContainer: form,
    tooltipOptions: {
        containerClass: 'error-tooltip'
    },
    // if you have a fixed header, either set a number or function here
    scrollToElementDiff: 0
}

Set options trough data-attributes

All Options can be set per form instance via data-attributes and will overwrite options that may have been set before. Boolean values are set trough integer values with 1 = true and 0 = false or just the attribute for true everything else is treated as String.

<form data-create-tooltips="0" data-ajax-submit-type="GET">

</form>

A Simple form with E-Mail-Validation

The following form has an HTML5 email input type defined, the input field is also required.

<input type="email" required/>


Another form, but with disabled tooltips and appendError set to true


<form data-append-error data-create-tooltips="0">
    <!-- [...] -->
</form>

Custom Messages

By Default all error messages are provided by the browser. The Default errorMessageHandler supports custom messages trough the data-validation-message attribute. You can provide your own Message handler by using the following static class method:

FlexCss.Form.registerErrorMessageHandler(
    function(field, validity){

    }
);

The following form contains one field with a custom error message


Example

<input required data-validation-message="Dude, E-Mail please!" type="email">

Custom Validation

Following form has custom validators registered. One will try to ask for a free username on the server. A second one will make sure that the passwords are equal. Before running custom validations, all default validators will be asked (like required, type etc.).

Register your Account

Try "BowlingX", this user might be available ;)


FlexCss.Form expects all Validators to return a promise with either false for invalid or true for a valid result. Registering a custom validator is easy like:

FlexCss.Form.registerValidator('inline-validate', function (field) {
    return new Promise(function (resolve) {
        resolve(true) // or resolve(false)
    });
});

Validators can be set with the data-validate attribute.


Setup Error-Messages in validator

Sample of equals validator. A field's error message can bet set with field.setCustomValidity

FlexCss.Form.registerValidator('equals', function (field) {
    var fieldThatShouldBeEqual = field.getAttribute('data-validate-equals'),
        fieldValue = document.getElementById(fieldThatShouldBeEqual);
        return new Promise(function (r) {
            var equals = field.value === fieldValue.value;
            if (!equals) {
                field.setCustomValidity('Passwords do not match.');
            }
        r(equals);
    });
});

Exclude hidden fields

Due the dynamic of a form, it's sometimes necessary to check if a field is hidden and skip validation. Because this check might be expansive we opt in for it with data-validate-visibility on each field that might be invisible in the future.

### Example

The following form shows a toggleable Region that will be validated when visible


A Toggleable legend

You should really open this, there might be Dragons behind ;)

User-Profile

Disable inline-validation for single Fields

Sometimes your user might be feel uncomfortable with a field being inline validated (and just validate in on submit). You can disable inline-validation on field by field basis with data-disable-inline-validation.

Example



Group Inputs to one label

It may be a requirement to group multiple input invalid-states to one label.

The following example demonstrates that with 3 Select-Widgets defining a birthday field. To archive this behaviour it’s possible to define a label that should be set to invalid with the attribute data-custom-label. It will only be valid if all referenced widgets are valid.


please provide your birthday, we will not publish your age...


Events

FlexCss.Form has some build in event’s that are fired as CustomEvent and are catchable with document.addEventListener(name).

Name Function
flexcss.form.ready Fires after form event’s have been bind.
flexcss.form.submit Fires if a form has been submitted (and though successfully passed validation), the event is cancelable with preventDefault().
flexcss.form.afterAjaxSubmit Fires right after the form has been submitted as XHR.
flexcss.form.ajaxCompleted Fires right after the ajax call has been completed (either successful or unsuccessful).

Remote / XHR

It’s possible to submit your form as XHR Request.

To enable that you just need to add an data-attribute data-remote and optional data-remote-action to specify where to POST (default) the form. You may also specify if the form should be submitted as FormData or as a JSON payload with either just data-remote or data-remote="json"


Remote Validation

You may register a remote validation handler with

FlexCss.Form.registerGlobalRemoteValidationFunction((request) => {})

The instance of the form is bind to the callback function, so you can use the internal API.


API

  • this.handleValidation(fieldsThatHaveErrorsArray, optionalFocus) will validate the given fields and eventually focus the first error

Example

Consult the fetch-api for more information how to handle a request promise

FlexCss.Form.registerGlobalRemoteValidationFunction(function(req) {
 // TODO: .. code to extract error messages from server response
 req.text().then(function (responseText) {
     // TODO: .. code to extract the fields that have an error
     // A field is marked as invalid with the following HTML5-API:
     field.setCustomValidity('Invalid field state');

     var fieldsThatHaveErrorsArray = [/*[...]*/],
         firstErrorField = fieldsThatHaveErrorsArray[0];

     // handle validation for fields, (second parameter focuses first error)
     this.handleValidation(fieldsThatHaveErrorsArray, true);
 }.bind(this));
});

Other Frameworks

FlexCss.Form is a pure JavaScript solution and does not depend on a specific markup. However I make the following assumptions:

  • Invalid fields (and related labels) will get the class invalid (configurable).
  • Elements should be nested in a wrapper div if you are using appendError (otherwise random things might happen).
    • Errors are appended on this wrapper div.
  • The appendError container has the class form-error (configurable)

Bootstrap

The following shows a sample implementation with Bootstrap (with both createTooltips and appendError enabled for demonstration)

See the Pen yNyZgw by David Heidrich (@BowlingX) on CodePen.