logo
Roman Kovalchik
Contact
Development

Form.js. jQuery library for working with forms via AJAX

Oct 12, 2021
73
<!-- CDN -->
<script src="https://cdn.jsdelivr.net/gh/Kovalchik8/form-js@1.0.6/form.min.js"></script>
  1. Description
  2. Usage example
  3. Fields attributes
  4. Options
  5. Events
  6. User interface
  7. WordPress full example

Description

Form.js is a tiny library that makes it much easier to work with forms asynchronously on the client side. Regardless of the complexity of the form markup, all required fields will be validated and sent to the server with a few lines of code.

Implementation in the form of a class makes it possible to export / import the library as a separate module.

Field type [file] is currently not supported.

Usage example

Client side:

<!-- basic example of HTML -->
<form id="main-form">
  <label data-subject-for="fname" for="fname-id">First name:</label>
  <input type="text" id="fname-id" name="fname">

  <label data-subject-for="email" for="email-id">Email:</label>
  <input type="email" id="email-id" name="email" required>

  <button type="submit">Submit</button>
</form>

<!-- including scripts -->
<script src="jquery.js"></script>
<script src="form.js"></script>

<script>
  var form = $('#main-form')
    
  var ajax_data = {
    subject: 'Main Form From My Site';
  }

  // creating form
  new Form({
    form: form, // required
    url: '/action.php', // required
    ajax_data: ajax_data // optional
  })

  // event after form was sent
  form.on('sent', (e, response) => {
    console.log(response)
  })
</script>

Server side (PHP):

<?php // action.php

$message = '';
$result = [
  'success' => false, // determines whether the form will be reset on the client side after submission
  'message' => 'Message was not sent'
];

$form_subject = $_POST['subject'];
$form_fields = $_POST['fields']; // multidimensional array with form fields
$headers  = "Content-type: text/html; charset=utf8 \r\n";

foreach($form_fields as $field)
  $message .= '<b>' .  $field['subject'] . '</b> ' .  $field['value'] . '<br><br>';

if (mail('admin@gmail.com', $form_subject, $message, $headers) )
  $result = ['success' => true, 'message' => 'Message was sent'];

echo json_encode($result); // returned data in JSON format
die();

Fields attributes

The [data-subject-for] HTML attribute binds the value of a field or several fields to the text that is inside a tag with this attribute.

form js subject

This is handy when you have multiple fields with the same [name] attribute. Accordingly, all these fields answer the same question inside the form:

<p data-subject-for="fav-animals">Fav animals:</p>
  
<input type="checkbox" id="cat-id" name="fav-animals" value="cat">
<label for="cat-id">Cat</label>

<input type="checkbox" id="dog-id" name="fav-animals" value="Dog">
<label for="dog-id">Dog</label>

With this example, the fields will be sent like this:

fields: {
  fav-animals: {
    subject: "Fav animals:",
    value: "cat, dog" // comma separated
  }
}

The subject value for each field is assigned according to the following priority depends on presence of attributes/tags in the form markup:

  1. The text of any tag with [data-subject-for] attribute, the value of which contains the field’s [name].
  2. The text of the tag <label> with [for] attribute, the value of which contains the field’s [id].
  3. The value of [placeholder] attribute of the field.
  4. The value of [name] attribute of the field.
<!-- 2. subject = Email -->
<label for="email-field-id">Email</label>
<input type="email" name="email" id="email-field-id">

<!-- 3. subject = Your email address -->
<input type="email" name="email" placeholder="Your email address">

<!-- 4. subject = your-email -->
<input type="email" name="your-email">

Options

new Form({
  form: $('form'),
  url: '/action.php',
  ajax_data: {
    subject: 'Main Form From My Site'
  },
  validators: {
    password: /^.{8,16}$/,
  },
  custom_ui: true,
  test_mode:  true,
  loading_target: $('form').closest('.form-wrapper')
})

form (required)

Form to submit

form: $('#main-form') // jquery object

url (required)

Link for submitting form data

url: '/action.php'  // string

ajax_data (optional)

Additional data that will be sent along with the form data

ajax_data: { // object
  subject: 'Main Form From My Site'
}  

validators (optional)

Regular expressions for fields validation by the [type] or [name] attributes.
You can override existing validations for types [email], [tel], [password].
Or add new ones, for example, for a field with the type [number].

validators: { // object
  password: /^.{8,32}$/, // validation for the field type="password"
  first_name: /^[a-z ,.'-]+$/i // validation for the field name="first_name"
}

custom_ui (optional)

Determines whether the default browser field validation functionality will be ignored (by the attributes [required], [type = email], [pattern], etc.).
Still, the validation will remain completely working – will be controlled by the library using the ‘error’ class for form fields, and js event field_status_changed.
The same effect can be achieved by using the [novalidate] attribute on the <form>
tag.

custom_ui: true // false by default

test_mode (optional)

If true, the object with the form data will be printed to the console before submitting. The server’s response will also be displayed in the console.

test_mode: true // false by default

loading_target (optional)

By default, the loading class is assigned to the submit button while processing ajax request. Using this parameter, you can assign this class to another element.

loading_target: $('.form-wrapper') // jquery object

Events

‘sent’

Fires after the form has been submitted. Options:

  • event (event object)
  • response (server response)
form.on('sent', (event, response) => {
  console.log(response)
})

‘field_status_changed’

Fires when the validation status of a field has changed. Options:

  • event (event object)
  • field (jquery field object with changed validation status)
  • required (whether field is required, bool)
  • valid (is field valid, bool)
// example of usage 'field_status_changed' event
form.on('field_status_changed', (event, field, required, valid) => {

  if (required && !field.val()) {
  // required field is empty

  } else if (!valid) {
  // field is not empty, but invalid

  } else {
  // field is ready to send

  }
})
Full example on JSFiddle, with validation messages.

‘before_ajax’

Fires before ajax requeest sending. Parameters:

  • event (event object)
  • ajax_data (an object with data, including form field data, which is sent by a request to the server)

‘after_ajax’

Fires after ajax request is complete. Parameters:

  • event (event object)

User interface

All fields that have not been validated after attempting to submit the form will be validated on fly – each time their value changes.

Example with email field:

// custom_ui: true

input.error {
  background-color: rgba(250, 125, 125, 0.1)
}

The button that is responsible for submitting the form is assigned with ‘loading‘ class during request process:

// example of loading button
.loading {
  position: relative;
  overflow: hidden;
  &:after {
    content: url('img/icons/loader.svg');
    display: block;
    position: absolute;
    top: calc(50% + 2px);
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 2;
  }
  &:before {
    content: '';
    position: absolute;
    left: 0;
    bottom: 0;
    background-color: rgba(255, 255, 255, 0.6);
    top: 0;
    right: 0;
    z-index: 1;
  }
}

WordPress full example

HTML

<form id="main-form">
  <input type="text" name="fname" placeholder="Name" required>
  <input type="text" name="lname" placeholder="Surname" required>
  <button type="submit">Sent</button>
</form>

JavaScript

// main.js

var form = $('#main-form'),
  ajax_data = {
    action: 'send_email',
    subject: 'Main Form From My Site',
  }

new Form({
  form: form,
  url: WPLocalize.admin_ajax_url,
  ajax_data: ajax_data,
})

form.on('sent', (e, response) => {
  response = JSON.parse(response)
  if (response.message && response.message.length) 
    alert(response.message)
})

PHP

<?php // functions.php

add_action('wp_enqueue_scripts', function() {
  wp_enqueue_script('form-js', get_theme_file_uri('/js/form.js'), 'jquery', '1.0.0', true);
  wp_enqueue_script('main-js', get_theme_file_uri('/js/main.js'), 'jquery', microtime(), true);
  wp_localize_script('main-js', 'WPLocalize', array(
    'admin_ajax_url' => admin_url('admin-ajax.php'),
  ));
});

add_action('wp_ajax_nopriv_send_email', 'send_email');
add_action('wp_ajax_send_email', 'send_email');

function send_email() {

  $message = '';
  $result = [
    'success' => false,
    'message' => 'Error sending message'
  ];

  $headers  = "Content-type: text/html; charset=utf8 \r\n";
  $form_fields = $_POST['fields'];

  foreach($form_fields as $field_name => $field_data) {
    $message .= '<b>' . sanitize_text_field($field_data['subject']) . ':</b> ';
    $message .= sanitize_text_field($field_data['value']) . '<br><br>';
  }

  if (wp_mail('admin@gmail.com', sanitize_text_field($_POST['subject']), $message, $headers) )
    $result = ['success' => true, 'message' => 'Message sent'];

  echo wp_json_encode($result); // returned data in json format
  wp_die();
}

That’s all. Share your experience of using html forms and tips for improving the Form.js library in the comments.

Be kind.

Oct 12, 2021
Like 2

Leave a Reply

Your email address will not be published.

bowl-with-food-682x1024 Nutrition
Aug 30, 2021
68
0

How to gain weight for an ectomorph? Even on a vegetarian diet

Long story short, an ectomorph is a skinny person with pretty thin bones, a minimal percentage of subcutaneous...

learn-english-1024x570 Education
Sep 08, 2021
48
1

How to learn a foreign language. Practical guide

I have studied English since the first grade of high school, attending school Olympiads. After high school, I studied English at the institute...

helpersScss Development
Sep 19, 2021
78
0

Helpers.scss. Library for comfortable CSS workflow

Helpers.scss library adheres to the basic principles of the well-known TailwindCSS library. But on the author's opinion...