# Forms

A ready-to-use framework for form validation and ajax submission of forms.

###

About the Plugin

This module handles validation and submission of forms and displays the server's response. Any form type can be handled, as the script accepts a standard JSON response from the server (detailed below).

Google reCAPTCHA v2 and invisible reCAPTCHA are supported seamlessly. See our documentation on reCaptcha for more.

###

Initializing

The demo pages already include the following code. These steps are only necessary if you are building a page from scratch. Remove these references if you are not using this plugin to improve page load times.

1. ###### Load the initializer code in `index.js`

   - Declare the following import statement in `js/mrare/index.js`. This ensures that the initializer code is included in the `theme.js` bundle.

         import mrFormEmail from './form-email';

   - Ensure the following line appears in the `export` object:

         export {
         mrFormEmail,
         };

2. ###### Load the required CSS in `components.scss`

   - Declare the following import statement in `scss/custom/components.scss`:

       @import "components/optional/forms";

   SCSS for the animated loading button is included in `scss/custom/components/required/buttons.scss`. This file is loaded by default and should not be excluded.

###

Basic Usage

A basic form must meet the following requirements to function correctly

- `<form>` must have `data-form-email` attribute to be handled by this script
- `<form>` must have `novalidate` attribute as per Bootstrap Validation guidelines.
- `<form>` should have an `action` attribute pointing to server-side form handler
- `<form>` must contain a `div[data-success-message]` and `div[data-error-message]`
- `div[data-success-message]` and `div[data-error-message]` should have class `d-none`
- Required form inputs should have `required` attribute to engage browser validation.
- Submit `<button>` must be `type="submit"`
- Submit `<button>` should have `data-loading-text`
- Submit `<button>` should contain a single `<span>` for button text

##### Example

Below is a basic subscribe form with one email address input.

- The form submits to the Mailchimp handler included with the theme package.
- Alerts are used for `data-success-message` and `data-error-message`
- `btn-loading` class on the submit `<button>` is to enable loading animation.

    <form action="/forms/mailchimp.php" data-form-email novalidate>
      <div class="form-row">
        <div class="col-12">
          <input type="email" class="form-control mb-2" placeholder="Email Address" name="email" required>
        </div>
        <div class="col-12">
          <div class="d-none alert alert-success" role="alert" data-success-message>
            Thanks, a member of our team will be in touch shortly.
          </div>
          <div class="d-none alert alert-danger" role="alert" data-error-message>
            Please fill all fields correctly.
          </div>
          <button type="submit" class="btn btn-primary btn-loading btn-block" data-loading-text="Sending">
            <!-- Icon for loading animation -->
            <svg class="icon" width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>Icon For Loading</title><g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g><polygon points="0 0 24 0 24 24 0 24" opacity="0"></polygon></g><path d="M12,4 L12,6 C8.6862915,6 6,8.6862915 6,12 C6,15.3137085 8.6862915,18 12,18 C15.3137085,18 18,15.3137085 18,12 C18,10.9603196 17.7360885,9.96126435 17.2402578,9.07513926 L18.9856052,8.09853149 C19.6473536,9.28117708 20,10.6161442 20,12 C20,16.418278 16.418278,20 12,20 C7.581722,20 4,16.418278 4,12 C4,7.581722 7.581722,4 12,4 Z" fill="#000000" fill-rule="nonzero" transform="translate(12.000000, 12.000000) scale(-1, 1) translate(-12.000000, -12.000000) "></path></g></svg>
            <span>Subscribe</span>
          </button>
        </div>
      </div>
    </form>

###

Options

Options that can alter the behaviour of forms are listed below

Attribute | Default | Usage
--- | --- | ---
`action` | `forms/mail.php` | Apply to `<form>`. Controls which endpoint will receive the form submission. Must accept `POST` request. If no `action` is provided, the default will be used.
`data-feedback-delay` | `5000` | Apply to `<form>`. Length of time (in milliseconds) to show success/error feedback before fading out.
`data-success-redirect` | none | Apply to `<form>`. Redirects the current page when a successful submission occurs. Provide an absolute or relative URL.
`data-loading-text` | `"Sending"` | Apply to submit `<button>`. Translates text shown on button while form is submitting. Button text is returned to its previous value when form finishes submitting.

###

Validation

For custom Bootstrap form validation messages, you must add the `novalidate` boolean attribute to your `<form>`. This disables the browser default feedback tooltips, but still provides access to the form validation APIs in JavaScript, which are used by our script.

Upon submission of the form, the contents will be validated and the class `was-validated` will be applied the `<form>` element. This allows you to leverage the custom validation message behaviour provided by Bootstrap.

Please see the Bootstrap form validation docs for full details.

This example shows an exerpt from the Bootstrap Docs demonstrating how to add a small message below invalid form inputs.

    <form class="was-validated">
      <div class="mb-3">
        <label for="validationTextarea">Textarea</label>
        <textarea class="form-control is-invalid" id="validationTextarea" placeholder="Required example textarea" required></textarea>
        <div class="invalid-feedback">
          Please enter a message in the textarea.
        </div>
      </div>
      ...
      ...
      ...
    </div>

This is optional markup. A generic "Please check your form input" message may be used for more simple forms, instead of specifying an error message on each input.

###

Displaying Feedback

To display success and error messages, your form must contain two `<div>`s with `data-success-message` and `data-error-message` attributes respectively. By default the theme uses Bootstrap `div.alert` elements for this purpose.

- `div[data-error-message]` is shown when there is a general validation error on the form, or if the form could not be sent from the browser. If an error message is passed back from the server, it will be shown in this element.
- `div[data-success-message]` is shown when a `success` status is received from the server. The message sent from the server is shown in this element.

Apply class `d-none` to both of these elements, as they are hidden/shown by toggling the `d-none` class.

    <div class="d-none alert alert-success" role="alert" data-success-message>
      Thanks, a member of our team will be in touch shortly.
    </div>
    <div class="d-none alert alert-danger" role="alert" data-error-message>
      Please fill all fields correctly.
    </div>

###

Submit Button

A `<button>` element containing a `<span>` is required.

The script will replace the text content of the `<span>` when the form is submitted. The text specified in the `data-loading-text` attribute on the `<button>` will be shown momentarily while the form is sent. This feature makes it easy to translate to other languages.

When the form is finished sending, the original text is restored.

##### Plain submit button

    <button type="submit" class="btn btn-primary" data-loading-text="Sending">
      <span>Subscribe</span>
    </button>

##### Animated submit button

The `<button>` can show an animation while the form is sending to the server.

- Add class `btn-loading` to the `<button>`
- Add an element with class `icon` to the button. It will be hidden by the theme's CSS.

    <button type="submit" class="btn btn-primary btn-loading" data-loading-text="Sending">
      <!-- Icon for loading animation (hidden by CSS) -->
      <svg class="icon" width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>Icon For Loading</title><g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g><polygon points="0 0 24 0 24 24 0 24" opacity="0"></polygon></g><path d="M12,4 L12,6 C8.6862915,6 6,8.6862915 6,12 C6,15.3137085 8.6862915,18 12,18 C15.3137085,18 18,15.3137085 18,12 C18,10.9603196 17.7360885,9.96126435 17.2402578,9.07513926 L18.9856052,8.09853149 C19.6473536,9.28117708 20,10.6161442 20,12 C20,16.418278 16.418278,20 12,20 C7.581722,20 4,16.418278 4,12 C4,7.581722 7.581722,4 12,4 Z" fill="#000000" fill-rule="nonzero" transform="translate(12.000000, 12.000000) scale(-1, 1) translate(-12.000000, -12.000000) "></path></g></svg>
      <span>Subscribe</span>
    </button>

When the form is submitted, the class `btn-loading-animate` will be added to the button, and the icon will be shown.

By default, the icon in the theme is animated by a CSS `spin` animation.

When the form is finished sending, the `btn-loading-animate` class will be removed from the button and the icon will be hidden.

###

Translation

All text found in forms is translatable. This is achieved through the use of data attributes, and through editing responses returned by the server.

Elements to consider when translating to a language other than English:

- `data-loading-text` on submit `<button>`
- Error text in `data-error-message` element.
- Messages in the (optional) `div.invalid-feedback` elements
- Messages in the (optional) `div.valid-feedback` elements
- Success text in `data-success-message` element.
- Success and error messages returned from the server (see server-side pages for more)

###

reCAPTCHA

Forms can be easily reCAPTCHA-enabled with either Checkbox (I am not a robot) or invisible reCAPTCHA. See the main reCaptcha page for full details.

###

Server Response JSON

The script sends a `POST` request via jQuery's `ajax` function and expects a JSON object as a response with `status` being either `success` or `error`.

###### Example success response

    {
      "status":"success",
      "message":"Thanks, a member of our team will be in touch shortly."
    }

When status returns `"success"`, the returned `message` is shown as the text in the `data-success-message` element.

###### Example error response

    {
      "status":"error",
      "message":"There was an error communicating with MailChimp.  Please try again later.",
      "errorName":"MailChimp API Error",
      "errorDetail":"{Full error detail as JSON passed from MailChimp...}"
    }

When status contains `"error"`, the returned `message` is shown as the text in the `data-error-message` element. Responses containing `errorDetail` will be output to the browser console for ease of debugging errors from MailChimp API etc.

By adhering to the above JSON response format, you may create any server-side function to interface your forms with virtually any API.

###

Included Form Handlers

We currently provide server-side scripts to interface with SwiftMailer to send emails via SMTP and a Mailchimp script to handle mail list subscriptions.

See our server-side docs for more information.

###

Events

The `<form>` emits a `sent.mr.formEmail` event when the form is successfully submitted.

Listen for this event to collect analytics on successful submissions.

If using the `data-success-redirect` option, the event will not be fired before the page is redirected. Analytics can instead be collected from the loading of the destination page.

###

Errors

If the server responds with a detailed error message, the message will be displayed in the browser's console. This is helpful when debugging MailChimp API responses and other instances where accessing a readable server error is difficult.

Other errors may include but are not limited to:

- `404`: Check the `action` attribute - is the URL accessible from the internet?
- `500`: Check your server-side code for errors, the server is returning an "internal server error".
- (0 error): this appears when the request could not be sent to the server by jQuery. This could be due to your server's cross-origin request policy, or because you are requesting `http` from a page served over `https`.