PreviewForm: Form Data Preview Before Submit for JS & jQuery

File Size: 10KB
Views Total: 3183
Last Update:
Publish Date:
Official Website: Go to website
License: MIT
   
PreviewForm: Form Data Preview Before Submit for JS & jQuery

PreviewForm 2.0 is a dependency-free JavaScript library that adds a review-before-submit step to native HTML forms.

It collects labeled values from text fields, textareas, selects, radio groups, checkbox groups, outputs, and file inputs, then displays them in a dialog or page-takeover review screen.

Your existing jQuery projects can use the optional adapter with jQuery 3.7 or 4.x.

Features:

  • Dependency-free TypeScript core with ESM, CommonJS, and browser IIFE builds.
  • Optional adapter for jQuery 3.7+ and jQuery 4.x projects.
  • Native HTML form validation before the review screen opens.
  • Original form submission flow after your user confirms the review.
  • Dialog semantics, keyboard focus control, Escape cancellation, and focus restoration.
  • Automatic labels from associated labels, legends, ARIA attributes, names, and IDs.
  • Grouped radio buttons, checkbox groups, fieldsets, and custom review sections.
  • Sensitive-value masking with omit and reveal policies.
  • File name, MIME type, and file-size metadata in the review.
  • Edit actions that return focus to the selected form control.
  • Lifecycle callbacks and controller methods for application-level integration.

How To Use It:

CDN Setup With Vanilla JavaScript

Load the stylesheet first, followed by the browser build. Version 2 does not require jQuery for this setup.

<link rel="stylesheet" href="/dist/styles.css">
<script src="/dist/index.iife.js"></script>

Add A Native HTML Form

PreviewForm reads standard form controls and their existing labels. Fieldset legends become section headings by default.

<form id="application-form" action="/applications" method="post">
  <fieldset>
    <legend>Contact Details</legend>

    <label for="applicant-name">Full name</label>
    <input id="applicant-name" name="full_name" type="text" required>

    <label for="applicant-email">Email address</label>
    <input id="applicant-email" name="email" type="email" required>

    <label for="account-code">Account code</label>
    <input
      id="account-code"
      name="account_code"
      type="text"
      data-preview-mask="last4"
    >
  </fieldset>

  <fieldset>
    <legend>Application Details</legend>

    <label for="role">Preferred role</label>
    <select id="role" name="role" required>
      <option value="">Choose a role</option>
      <option value="frontend">Front-end developer</option>
      <option value="designer">Product designer</option>
    </select>

    <label for="resume">Resume</label>
    <input id="resume" name="resume" type="file" accept=".pdf,.doc,.docx">

    <button type="submit" name="action" value="submit">
      Review application
    </button>
  </fieldset>
</form>

Attach The Review Step

var applicationForm = document.querySelector("#application-form");

var applicationReview = PreviewForm.attachReview(applicationForm, {
  title: "Review your application",
  description: "Check each answer before you send the application.",
  confirmLabel: "Send application",
  cancelLabel: "Keep editing",
  sensitiveFields: "mask",
  files: "metadata"
});

The library intercepts the form submit event. It runs native validation first. A valid form opens the review screen, while an invalid form keeps the browser's normal validation messages. The confirm button submits the original form through its existing action and method.

NPM And ES Module Setup

npm install preview-form
import { attachReview } from "preview-form";
import "preview-form/styles.css";

var form = document.querySelector("#application-form");

var review = attachReview(form, {
  title: "Review your application",
  confirmLabel: "Submit"
});

jQuery Adapter Setup

The adapter requires jQuery 3.7 or newer and supports jQuery 4.x. Load jQuery before the adapter script. The adapter uses the jQuery instance already available on the page.

<link rel="stylesheet" href="/dist/styles.css">

<script src="/path/to/cdn/jquery.min.js"></script>
<script src="/dist/jquery.iife.js"></script>

<script>
$("#application-form").previewForm({
  title: "Review your application",
  yes: "Send application",
  no: "Keep editing",
  extratext: "Check each answer before submission."
});
</script>

The aliases yes, no, and extratext map to the v2 labels and description. Core v2 options also work through the adapter.

Install The jQuery Adapter In A Bundled Project

npm install preview-form jquery
npm install --save-dev @types/jquery
import $ from "jquery";
import { installJQueryAdapter } from "preview-form/jquery";
import "preview-form/styles.css";

installJQueryAdapter($);

$("#application-form").previewForm({
  title: "Review your application",
  confirmLabel: "Submit"
});

Available Options:

  • mode: Selects "dialog" or "page" review mode. Type: String. Default: "dialog".
  • title: Sets the review heading. Type: String. Default: "Review your answers".
  • description: Sets the text below the review heading. Type: String. Default: "Check your information before sending.".
  • confirmLabel: Sets the final submit button text. Type: String. Default: "Send".
  • cancelLabel: Sets the button text that returns to the form. Type: String. Default: "Keep editing".
  • editLabel: Sets the text for each field-level edit button. Type: String. Default: "Change".
  • editable: Adds or removes field-level edit buttons. Type: Boolean. Default: true.
  • includeEmpty: Shows empty optional fields as Not provided when set to true. Type: Boolean. Default: true.
  • sections: Groups entries by fieldset legend or data-preview-section. Type: Boolean. Default: true.
  • sensitiveFields: Uses "mask", "omit", or "reveal" for sensitive entries. Type: String. Default: "mask".
  • files: Uses "metadata", "filename", or "omit" for file inputs. Type: String. Default: "metadata".
  • labelResolver: Returns a custom label for a form control. The library falls back to its normal label lookup when the function returns no value. Type: Function. Default: Not set.
  • valueFormatter: Returns the display value for an entry after the library applies its normal formatting policy. Type: Function. Default: Not set.
  • onOpen: Runs after the review interface opens. Type: Function. Default: Not set.
  • onCancel: Runs when the user cancels the review or code calls close(). Type: Function. Default: Not set.
  • onConfirm: Runs before final submission. Return false to keep the review open and stop submission. Type: Function. Default: Not set.

jQuery Compatibility Options

  • yes: Legacy alias for confirmLabel.
  • no: Legacy alias for cancelLabel.
  • extratext: Legacy alias for description.
  • show_password: Reveals password controls when set to true. Other sensitive-looking fields keep the configured masking policy.
  • identifier: Uses each control's name or id as its review label when set to "name" or "id".

Core Functions:

  • attachReview(form, options): Attaches the review flow to one HTMLFormElement and returns a ReviewController.
  • collectEntries(form, options): Collects the current form controls into ReviewEntry objects without opening the review interface.
  • installJQueryAdapter($): Adds $.fn.previewForm to the supplied jQuery instance. Import it from preview-form/jquery.

API Methods:

attachReview() returns a controller for the attached form.

var review = PreviewForm.attachReview(
  document.querySelector("#application-form")
);

// Open the review after native validation passes.
review.open();

// Close the review and run onCancel.
review.close();

// Recollect current form values while the review is open.
review.refresh();

// Read the active ReviewContext or null.
var context = review.getContext();

// Remove the submit listener and generated review interface.
review.destroy();

jQuery Adapter Methods

// Open the attached review.
$("#application-form").previewForm("open");

// Recollect values while the review is open.
$("#application-form").previewForm("refresh");

// Remove the adapter instance and its generated interface.
$("#application-form").previewForm("destroy");

Callbacks And Review Context:

PreviewForm does not expose custom DOM events. Use its lifecycle callbacks for application logic.

var review = PreviewForm.attachReview(
  document.querySelector("#application-form"),
  {
    onOpen: function(context) {
      console.log(context.entries);
    },

    onCancel: function(context) {
      console.log("Review cancelled", context.submitter);
    },

    onConfirm: function(context) {
      var seats = Number(context.formData.get("seat_count"));

      if (seats > 20) {
        window.alert("Requests above 20 seats require sales approval.");
        return false;
      }
    }
  }
);

The callback receives a ReviewContext object with the original form, the active submit button, collected review entries, and a FormData instance. Each review entry contains the source control, field name, resolved label, displayed value, raw value, section, sensitive-state flag, and optional file summaries.

Field-Level Data Attributes:

  • data-preview-ignore: Excludes the control from the review.
  • data-preview-include="true": Includes a hidden input in the review. Hidden controls stay excluded by default.
  • data-preview-label: Replaces the detected label for one control.
  • data-preview-mask: A nonempty value marks the control as sensitive. Use "last4" to reveal only the final four characters.
  • data-sensitive: Marks a control as sensitive under the selected sensitive-field policy.
  • data-preview-section: Sets a section name on a containing element. Descendant controls use that section.

Advanced Examples:

Group Fields And Apply Per-Field Policies

<form id="checkout-form">
  <section data-preview-section="Delivery">
    <label for="delivery-name">Recipient</label>
    <input id="delivery-name" name="recipient" required>

    <label for="delivery-note">Delivery note</label>
    <textarea
      id="delivery-note"
      name="note"
      data-preview-label="Courier instructions"
    ></textarea>
  </section>

  <section data-preview-section="Payment Reference">
    <label for="reference-number">Reference number</label>
    <input
      id="reference-number"
      name="payment_reference"
      data-preview-mask="last4"
    >

    <input
      type="hidden"
      name="checkout_version"
      value="2026-07"
      data-preview-include="true"
      data-preview-label="Checkout version"
    >
  </section>

  <input type="text" name="tracking_source" data-preview-ignore>

  <button type="submit">Review order</button>
</form>

Format Labels And Values

PreviewForm.attachReview(
  document.querySelector("#quote-form"),
  {
    labelResolver: function(control) {
      if (control.name === "monthly_budget") {
        return "Estimated monthly budget";
      }
    },

    valueFormatter: function(control, value, entry) {
      if (control.name === "monthly_budget" && entry.rawValue) {
        return "$" + Number(entry.rawValue).toLocaleString("en-US");
      }

      return value;
    }
  }
);

Create A Draft Review Flow

A form with novalidate can open the review even when required fields are empty.

<form id="draft-profile" novalidate>
  <label for="display-name">Display name</label>
  <input id="display-name" name="display_name" required>

  <label for="bio">Biography</label>
  <textarea id="bio" name="bio"></textarea>

  <button type="submit">Review draft</button>
</form>

<script>
PreviewForm.attachReview(
  document.querySelector("#draft-profile"),
  {
    mode: "page",
    title: "Review draft profile",
    confirmLabel: "Save draft",
    includeEmpty: false
  }
);
</script>

Refresh A jQuery Review After A Dynamic Update

$("#team-form").previewForm({
  title: "Review team settings"
});

$("#load-plan").on("click", function() {
  $("#plan").val("business").trigger("change");

  // Rebuild the visible review when it is already open.
  $("#team-form").previewForm("refresh");
});

Alternatives And Related Resources:


This awesome jQuery plugin is developed by aniketan. For more Advanced Usages, please check the demo page or visit the official website.