0
# Element State Management
1
2
System for enabling and disabling form elements and links during processing, providing visual feedback to users and preventing double-submission issues.
3
4
## Capabilities
5
6
### Element Disabling
7
8
Disables elements and provides visual feedback during processing.
9
10
```javascript { .api }
11
/**
12
* Disable element and show loading state
13
* @param element - Element or Event containing target element to disable
14
*/
15
function disableElement(element: Element | Event): void;
16
```
17
18
**Usage Examples:**
19
20
```javascript
21
// Disable a button
22
const button = document.querySelector("#submit-btn");
23
Rails.disableElement(button);
24
25
// Disable during event handling
26
document.addEventListener("click", function(event) {
27
if (event.target.matches("[data-disable-with]")) {
28
Rails.disableElement(event);
29
}
30
});
31
32
// Works with different element types
33
const link = document.querySelector('a[data-disable-with="Processing..."]');
34
Rails.disableElement(link);
35
```
36
37
### Element Enabling
38
39
Re-enables elements and restores their original content.
40
41
```javascript { .api }
42
/**
43
* Re-enable element and restore original content
44
* @param element - Element or Event containing target element to enable
45
*/
46
function enableElement(element: Element | Event): void;
47
```
48
49
**Usage Examples:**
50
51
```javascript
52
// Re-enable a button
53
const button = document.querySelector("#submit-btn");
54
Rails.enableElement(button);
55
56
// Enable after AJAX completion
57
Rails.ajax({
58
type: "POST",
59
url: "/api/data",
60
beforeSend: () => Rails.disableElement(submitButton),
61
complete: () => Rails.enableElement(submitButton)
62
});
63
64
// Enable elements after page show (browser back/forward)
65
window.addEventListener("pageshow", function() {
66
Rails.$("[data-disable-with]:disabled").forEach(Rails.enableElement);
67
});
68
```
69
70
### Disabled Element Handler
71
72
Prevents actions on disabled elements by stopping event propagation.
73
74
```javascript { .api }
75
/**
76
* Handle clicks on disabled elements by stopping all events
77
* @param event - Event to handle (typically click event)
78
*/
79
function handleDisabledElement(event: Event): void;
80
```
81
82
**Usage Examples:**
83
84
```javascript
85
// Automatically prevent actions on disabled elements
86
document.addEventListener("click", Rails.handleDisabledElement);
87
88
// Manual usage in custom event handlers
89
button.addEventListener("click", function(event) {
90
if (this.disabled) {
91
Rails.handleDisabledElement(event); // Stops everything
92
return;
93
}
94
// Normal click handling
95
});
96
```
97
98
## Data Attribute Integration
99
100
Elements are automatically managed based on data attributes:
101
102
### data-disable-with
103
104
Replaces element content with loading text during processing:
105
106
```html
107
<!-- Button shows "Creating..." when clicked -->
108
<button type="submit" data-disable-with="Creating...">Create Post</button>
109
110
<!-- Link shows "Loading..." when clicked -->
111
<a href="/posts/1" data-remote="true" data-disable-with="Loading...">View Post</a>
112
113
<!-- Input shows loading text in value -->
114
<input type="submit" value="Save" data-disable-with="Saving..." />
115
```
116
117
### data-disable
118
119
Disables element without changing its content:
120
121
```html
122
<!-- Button becomes disabled but keeps original text -->
123
<button type="submit" data-disable="true">Submit</button>
124
125
<!-- Link becomes disabled and click events are prevented -->
126
<a href="/posts/1" data-method="delete" data-disable="true">Delete</a>
127
```
128
129
## Element-Specific Behavior
130
131
### Form Elements (Buttons, Inputs)
132
133
```javascript
134
// Button content replacement
135
<button data-disable-with="Processing...">Submit</button>
136
// Becomes: <button disabled>Processing...</button>
137
138
// Input value replacement
139
<input type="submit" value="Save" data-disable-with="Saving..." />
140
// Becomes: <input type="submit" value="Saving..." disabled />
141
```
142
143
### Links
144
145
```javascript
146
// Link content replacement and click prevention
147
<a href="/posts" data-disable-with="Loading...">Posts</a>
148
// Becomes: <a href="/posts">Loading...</a> (with click handler to stop events)
149
```
150
151
### Forms
152
153
Entire forms can be disabled during submission:
154
155
```html
156
<form data-remote="true">
157
<input type="text" data-disable-with="Processing..." />
158
<button type="submit" data-disable-with="Submitting...">Submit</button>
159
</form>
160
```
161
162
## Automatic Integration
163
164
Rails UJS automatically manages element states during:
165
166
- **Form submission**: Disables all form elements with disable attributes
167
- **AJAX requests**: Disables trigger elements during request lifecycle
168
- **Page navigation**: Re-enables elements when returning via browser history
169
- **Remote forms**: Manages submit button states during AJAX form processing
170
171
## Selectors Used
172
173
Rails UJS uses these selectors to identify elements for state management:
174
175
```javascript { .api }
176
// Elements that can be disabled during form submission
177
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";
178
179
// Elements that can be re-enabled after processing
180
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";
181
182
// Links that can be disabled
183
const linkDisableSelector = "a[data-disable-with], a[data-disable]";
184
185
// Buttons that can be disabled
186
const buttonDisableSelector = "button[data-remote][data-disable-with], button[data-remote][data-disable]";
187
```
188
189
## State Management Lifecycle
190
191
1. **Initial State**: Elements are enabled with original content
192
2. **Trigger Event**: User clicks/submits element with disable attributes
193
3. **Disable Phase**: Element is disabled, content replaced if `data-disable-with` present
194
4. **Processing**: Element remains disabled during AJAX request or form submission
195
5. **Completion**: Element is re-enabled, original content restored
196
6. **Error Handling**: Element is re-enabled even on errors to prevent permanent lock
197
198
## Content Editable Support
199
200
The system automatically skips content editable elements to prevent interference with rich text editors:
201
202
```javascript
203
// Content editable elements are never disabled
204
<div contenteditable="true" data-disable-with="Processing...">
205
Rich text content...
206
</div>
207
```