# Front-end JS

The default [Form Template](docs:feature-tour/form-templates) used by Formie uses custom JS when rendering the form. This is to provide out-of-the-box functionality for forms, so you don't need to worry about things like validation, multi-page setup and Ajax submissions.

The default JavaScript is split into two files, and can be disabled in your [Form Templates](docs:feature-tour/form-templates) should you wish to implement your own JavaScript for functionality. Both files are bundled in a single JS file. The gzipped size of this file is roughly 20kb, and comes with all required polyfills to support [90% browser coverage](https://browserl.ist/?q=defaults).

It is also loaded using `defer` to ensure loading doesn't block the page render.

## Form Base
This JavaScript is minimal, providing event hooks for the form and fields, along with easy translation handling for strings. It also provides these event hooks so that Captchas like ReCAPTCHA can work correctly.

## Form Theme 
This JavaScript is a little more opinionated, and provides the following:

- Translatable client-side validation (via [Bouncer.js](https://github.com/cferdinandi/bouncer))
- Multi-page handling
- Success/error message handling
- Ajax submissions
- Loading indicator
- Disabling the submit button when clicked
- Prompting the user they have unsaved changes, if trying to navigate away

## Field-specific JS
Some fields also require additional JS to be rendered alongside the field. Fortunately, these are lazy-loaded only if the field is actually used in the form. These are:

### Checkboxes/Radios
This helper provides toggling of `aria-checked` and `aria-required` attributes for checkboxes and radios. In addition, there is currently no native HTML5 validation behaviour for validating a group of checkbox fields. This is if you want the user to select at least one option in a collection of checkboxes. This helper also provides this functionality.

### File Upload
This helper is provided to assist with limits set on the field, by the types of files allowed to upload and the file-size limit.

### Repeater
This helper provides functionality to the Repeater field, namely by handling adding or removing new rows of repeatable content.

### Table
This helper provides functionality to the Table field, namely by handling adding or removing new rows of repeatable content.

### Tags
This helper provides functionality to create tags for a Tag field. It uses [Tagify](https://github.com/yairEO/tagify).

### Text
For Single-line Text and Multi-line text fields, and if the `Limit` options are set, this will display a counter for either characters or words to limit the text for these fields. It will also prevent typing past these limits.

## Form Templates
Your [Form Templates](docs:feature-tour/form-templates) can control where and how the JS for a form is rendered. You can also disable the "Form Base" or "Form Theme" JavaScript, if you wish to write your own JS.

:::warning
Be aware that if disabling the "Form Base" you will lose Formie's submit-handler binding on the form. This will mean reCAPTCHA will not work on your forms, as it relies on interrupting the submission of a form to validate. You will need to manage reCAPTCHA yourself.
:::

For example, if you wish to disable the "Form Theme", client-side validation will no longer work. It will be up to you to implement this behaviour for your site.

### Render Location
By default, Formie will render a single `formie.js` right before the `</body>` tag at the end of the page. You can choose to either render it `Inside Form`, or `Manual` - Manual essentially disabling rendering.

### Manual Render
You can select exactly where you'd like the JavaScript for forms to be output on the page, using `craft.formie.renderFormJs()`

```twig
<div class="form-wrap">
    {{ craft.formie.renderForm('myForm') }}
</div>

{{ craft.formie.renderFormJs('myForm') }}
```

You could also use a Form object instead of the handle.

```twig
{% set form = craft.formie.forms({ handle: 'myForm' }).one() %}

<div class="form-wrap">
    {{ craft.formie.renderForm(form) }}
</div>

{{ craft.formie.renderFormJs(form) }}
```

Here, we have split the rendering of the form to the HTML for the form, then the JS for the form. This can be particularly useful for Vue.js, where `<script>` elements generated by Formie shouldn't be included within a template - or if your page doesn't have a `</body>` to attach it to.

There are also further scenarios where you want more fine-grained control over the JavaScript, which we'll explore in [JavaScript API](docs:developers/javascript-api).

## Submit with JavaScript (Ajax)
You can also trigger form submission through JavaScript.

:::code
```js JavaScript
let $form = document.querySelector('#formie-form-1');
let data = new FormData($form);

fetch('/', {
    method: 'post',
    body: data,
    headers: {
        'Accept': 'application/json',
        'X-Requested-With': 'XMLHttpRequest',
    },
}).then(function(response) {
    response.json().then(function(data) {
        console.log(data);
    });
});
```

```js jQuery
let data = $('#formie-form-1').serialize();

$.ajax({
    type: 'POST',
    url: '/',
    data: data,
    cache: false,
    dataType: 'json',
    error: function(jqXHR, textStatus, errorThrown) {
        console.log(jqXHR)
    },
    success: function(response) {
        console.log(response);
    }
});
```
:::

If you're unable to use `FormData` or `serialize()`, or you're constructing the payload for the action yourself, you'll need to provide the CSRF token and the action to perform in your payload.

```twig
<script type="text/javascript">
    window.csrfTokenName = "{{ craft.app.config.general.csrfTokenName|e('js') }}";
    window.csrfTokenValue = "{{ craft.app.request.csrfToken|e('js') }}";
</script>
```

```js
let data = {
    action: 'formie/submissions/submit',
    handle: 'contactForm',
    siteId: 1,
    fields: {
        yourName: 'Peter Sherman',
        emailAddress: 'psherman@wallaby.com',
        message: 'Hello there!',
    },
};

// Add the CSRF Token
data[csrfTokenName] = csrfTokenValue;
```
