Ruby on Rails unobtrusive scripting adapter that enables modern JavaScript behaviors through HTML5 data attributes
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Form serialization and element management utilities for handling form submissions, data collection, and form state management in Rails UJS.
Converts form elements and their data into URL-encoded strings suitable for HTTP requests.
/**
* Serialize form or element data to URL-encoded string
* @param element - Form element or individual input to serialize
* @param additionalParam - Optional additional parameter to include
* @returns URL-encoded string of form data
*/
function serializeElement(element: Element, additionalParam?: {name: string, value: string}): string;Usage Examples:
const form = document.querySelector("form");
// Serialize entire form
const formData = Rails.serializeElement(form);
console.log(formData); // "title=Hello&body=World&commit=Create"
// Serialize with additional parameter
const dataWithToken = Rails.serializeElement(form, {
name: "authenticity_token",
value: "abc123"
});
// Serialize individual input
const input = document.querySelector("input[name=title]");
const inputData = Rails.serializeElement(input);
console.log(inputData); // "title=Hello"
// Used in AJAX requests
Rails.ajax({
type: "POST",
url: "/posts",
data: Rails.serializeElement(form)
});Gets form elements that match a specific selector, handling both forms and individual elements.
/**
* Get form elements matching selector
* @param form - Form element or container element
* @param selector - CSS selector for elements to find
* @returns Array of matching elements
*/
function formElements(form: Element, selector: string): Element[];Usage Examples:
const form = document.querySelector("form");
// Get all submit buttons in form
const submitButtons = Rails.formElements(form, "input[type=submit], button[type=submit]");
// Get elements to disable during submission
const disableElements = Rails.formElements(form, "[data-disable-with]");
disableElements.forEach(el => Rails.disableElement(el));
// Get file inputs for special handling
const fileInputs = Rails.formElements(form, "input[type=file]");
// Works with non-form containers too
const container = document.querySelector(".form-container");
const inputs = Rails.formElements(container, "input, select, textarea");Handles submit button clicks to track which button was used for form submission.
/**
* Handle form submit button clicks to track submission context
* @param event - Click event from submit button
*/
function formSubmitButtonClick(event: Event): void;Usage Examples:
// Automatically handled by Rails UJS for these elements:
// form input[type=submit]
// form input[type=image]
// form button[type=submit]
// form button:not([type])
// input[type=submit][form]
// button[type=submit][form]
// The clicked button info is stored and used in form submission:
const form = document.querySelector("form");
const submitButton = form.querySelector("button[name=commit]");
// After button click, Rails UJS stores:
// Rails.getData(form, "ujs:submit-button") = { name: "commit", value: "Create" }
// Rails.getData(form, "ujs:formnovalidate-button") = button.formNoValidate
// Rails.getData(form, "ujs:submit-button-formaction") = button.formAction
// Rails.getData(form, "ujs:submit-button-formmethod") = button.formMethodThe serialization process includes:
input[type=text], input[type=email], etc.<textarea> elementsinput[type=hidden]Elements that are NOT serialized:
[disabled] attribute presentname attribute<fieldset disabled>input[type=checkbox]:not(:checked)input[type=radio]:not(:checked)input[type=file] (handled separately as FormData)// Select elements - includes all selected options
<select name="categories" multiple>
<option value="1" selected>Tech</option>
<option value="2" selected>News</option>
</select>
// Serializes as: "categories=1&categories=2"
// Checkbox groups with same name
<input type="checkbox" name="tags[]" value="ruby" checked>
<input type="checkbox" name="tags[]" value="rails" checked>
// Serializes as: "tags%5B%5D=ruby&tags%5B%5D=rails"
// Submit button information
<button type="submit" name="commit" value="publish">Publish</button>
// When clicked, adds: "commit=publish"Forms with data-remote="true" use serialization for AJAX submission:
<form action="/posts" method="post" data-remote="true">
<input type="text" name="title" value="Hello">
<textarea name="body">World</textarea>
<button type="submit" name="commit" value="Create">Create Post</button>
</form>// Rails UJS automatically:
// 1. Prevents normal form submission
// 2. Serializes form data: "title=Hello&body=World&commit=Create"
// 3. Makes AJAX request with serialized data
// 4. Handles response appropriatelyForms with file inputs use FormData instead of URL encoding:
<form action="/uploads" method="post" enctype="multipart/form-data" data-remote="true">
<input type="file" name="document">
<input type="text" name="title">
<button type="submit">Upload</button>
</form>// Rails UJS detects multipart forms and:
// 1. Creates FormData object instead of URL-encoded string
// 2. Appends all form fields to FormData
// 3. Includes clicked submit button data
// 4. Sends as multipart/form-dataRails method override is handled through hidden fields:
<form action="/posts/1" method="post">
<input type="hidden" name="_method" value="patch">
<input type="text" name="title">
</form>The _method field is included in serialization to enable REST methods.
Form elements are automatically managed during submission:
// Before submission:
const disableElements = Rails.formElements(form, "[data-disable-with]:enabled");
disableElements.forEach(Rails.disableElement);
// After completion:
const enableElements = Rails.formElements(form, "[data-disable-with]:disabled");
enableElements.forEach(Rails.enableElement);Rails UJS uses these selectors for form handling:
// Forms that should be processed by Rails UJS
const formSubmitSelector = "form:not([data-turbo=true])";
// Submit buttons and inputs in forms
const formInputClickSelector = "form:not([data-turbo=true]) input[type=submit], form:not([data-turbo=true]) input[type=image], form:not([data-turbo=true]) button[type=submit], form:not([data-turbo=true]) button:not([type]), input[type=submit][form], input[type=image][form], button[type=submit][form], button[form]:not([type])";
// Elements to disable during form submission
const formDisableSelector = "input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled";
// File inputs that need special handling
const fileInputSelector = "input[name][type=file]:not([disabled])";Install with Tessl CLI
npx tessl i tessl/npm-rails--ujs