CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-rails--ujs

Ruby on Rails unobtrusive scripting adapter that enables modern JavaScript behaviors through HTML5 data attributes

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

form-handling.mddocs/

Form Handling

Form serialization and element management utilities for handling form submissions, data collection, and form state management in Rails UJS.

Capabilities

Form Serialization

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)
});

Form Element Selection

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");

Submit Button Tracking

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.formMethod

Form Serialization Details

Included Elements

The serialization process includes:

  • Text inputs: input[type=text], input[type=email], etc.
  • Textareas: All <textarea> elements
  • Select elements: Single and multiple select dropdowns
  • Checkboxes: Only checked checkboxes
  • Radio buttons: Only selected radio buttons
  • Hidden inputs: input[type=hidden]
  • Submit buttons: The clicked submit button (if any)

Excluded Elements

Elements that are NOT serialized:

  • Disabled elements: [disabled] attribute present
  • Elements without names: Missing name attribute
  • Fieldset disabled children: Elements inside <fieldset disabled>
  • Unchecked checkboxes: input[type=checkbox]:not(:checked)
  • Unselected radios: input[type=radio]:not(:checked)
  • File inputs: input[type=file] (handled separately as FormData)

Special Handling

// 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"

Form Processing Integration

Remote Form Handling

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 appropriately

File Upload Handling

Forms 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-data

Form Method Override

Rails 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.

Element State During Submission

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);

Common Selectors

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

docs

ajax-remote.md

csrf-protection.md

dom-utilities.md

element-state.md

event-system.md

feature-handlers.md

form-handling.md

index.md

tile.json