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

element-state.mddocs/

Element State Management

System for enabling and disabling form elements and links during processing, providing visual feedback to users and preventing double-submission issues.

Capabilities

Element Disabling

Disables elements and provides visual feedback during processing.

/**
 * Disable element and show loading state
 * @param element - Element or Event containing target element to disable
 */
function disableElement(element: Element | Event): void;

Usage Examples:

// Disable a button
const button = document.querySelector("#submit-btn");
Rails.disableElement(button);

// Disable during event handling
document.addEventListener("click", function(event) {
  if (event.target.matches("[data-disable-with]")) {
    Rails.disableElement(event);
  }
});

// Works with different element types
const link = document.querySelector('a[data-disable-with="Processing..."]');
Rails.disableElement(link);

Element Enabling

Re-enables elements and restores their original content.

/**
 * Re-enable element and restore original content
 * @param element - Element or Event containing target element to enable
 */
function enableElement(element: Element | Event): void;

Usage Examples:

// Re-enable a button
const button = document.querySelector("#submit-btn");
Rails.enableElement(button);

// Enable after AJAX completion
Rails.ajax({
  type: "POST",
  url: "/api/data",
  beforeSend: () => Rails.disableElement(submitButton),
  complete: () => Rails.enableElement(submitButton)
});

// Enable elements after page show (browser back/forward)
window.addEventListener("pageshow", function() {
  Rails.$("[data-disable-with]:disabled").forEach(Rails.enableElement);
});

Disabled Element Handler

Prevents actions on disabled elements by stopping event propagation.

/**
 * Handle clicks on disabled elements by stopping all events
 * @param event - Event to handle (typically click event)
 */
function handleDisabledElement(event: Event): void;

Usage Examples:

// Automatically prevent actions on disabled elements
document.addEventListener("click", Rails.handleDisabledElement);

// Manual usage in custom event handlers
button.addEventListener("click", function(event) {
  if (this.disabled) {
    Rails.handleDisabledElement(event); // Stops everything
    return;
  }
  // Normal click handling
});

Data Attribute Integration

Elements are automatically managed based on data attributes:

data-disable-with

Replaces element content with loading text during processing:

<!-- Button shows "Creating..." when clicked -->
<button type="submit" data-disable-with="Creating...">Create Post</button>

<!-- Link shows "Loading..." when clicked -->
<a href="/posts/1" data-remote="true" data-disable-with="Loading...">View Post</a>

<!-- Input shows loading text in value -->
<input type="submit" value="Save" data-disable-with="Saving..." />

data-disable

Disables element without changing its content:

<!-- Button becomes disabled but keeps original text -->
<button type="submit" data-disable="true">Submit</button>

<!-- Link becomes disabled and click events are prevented -->
<a href="/posts/1" data-method="delete" data-disable="true">Delete</a>

Element-Specific Behavior

Form Elements (Buttons, Inputs)

// Button content replacement
<button data-disable-with="Processing...">Submit</button>
// Becomes: <button disabled>Processing...</button>

// Input value replacement  
<input type="submit" value="Save" data-disable-with="Saving..." />
// Becomes: <input type="submit" value="Saving..." disabled />

Links

// Link content replacement and click prevention
<a href="/posts" data-disable-with="Loading...">Posts</a>
// Becomes: <a href="/posts">Loading...</a> (with click handler to stop events)

Forms

Entire forms can be disabled during submission:

<form data-remote="true">
  <input type="text" data-disable-with="Processing..." />
  <button type="submit" data-disable-with="Submitting...">Submit</button>
</form>

Automatic Integration

Rails UJS automatically manages element states during:

  • Form submission: Disables all form elements with disable attributes
  • AJAX requests: Disables trigger elements during request lifecycle
  • Page navigation: Re-enables elements when returning via browser history
  • Remote forms: Manages submit button states during AJAX form processing

Selectors Used

Rails UJS uses these selectors to identify elements for state management:

// Elements that can be disabled 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";

// Elements that can be re-enabled after processing
const formEnableSelector = "input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled";

// Links that can be disabled
const linkDisableSelector = "a[data-disable-with], a[data-disable]";

// Buttons that can be disabled  
const buttonDisableSelector = "button[data-remote][data-disable-with], button[data-remote][data-disable]";

State Management Lifecycle

  1. Initial State: Elements are enabled with original content
  2. Trigger Event: User clicks/submits element with disable attributes
  3. Disable Phase: Element is disabled, content replaced if data-disable-with present
  4. Processing: Element remains disabled during AJAX request or form submission
  5. Completion: Element is re-enabled, original content restored
  6. Error Handling: Element is re-enabled even on errors to prevent permanent lock

Content Editable Support

The system automatically skips content editable elements to prevent interference with rich text editors:

// Content editable elements are never disabled
<div contenteditable="true" data-disable-with="Processing...">
  Rich text content...
</div>

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